![]()
|
|||||||||||||||||||||||||||||||||||
Синтаксис
Лабораторная работа 1. Процессы и их ранги. Знакомство с примерами программ и средой MPI
Среда параллельного программирования Message Passing Interface (MPI)
Порядок работы 1. Подключиться к серверу, определив его наличие в сети с помощью команды ip Команда ip используется для назначения адреса сетевому интерфейсу и/или конфигурирования параметров сетевого интерфейса в дистрибутивах Linux. Эта команда заменяет собой ныне устаревшую команду ifconfig в современных дистрибутивах Linux. Команда ip может использоваться для следующих целей: · Узнать какие интерфейсы сконфигурированы в системе. · Запросить статус IP интерфейса. · Сконфигурировать локальный, Ethernet и другие интерфейсы. · Пометить интефейс как up или down. · Сконфигурировать или изменить статическую маршрутизацию или маршрутизацию по умолчанию. · Сконфигурировать туннель через IP. · Сконфигурировать содержимое ARP или NDISC кэша. · Назначить IP адресы, маршруты, подсети и другую IP информацию на интерфейс. Синтаксис ip OBJECT COMMAND ip [options] OBJECT COMMAND ip OBJECT help
Выполнение: Назначение команды ip
Введите НА СЕРВЕРЕ (получив доступ к его терминалу) следующую команду чтобы получить список всех ip адресов назначенных всем сетевым интерфейсам: ip a или ip addr
Пример вывода: 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
Вы можете выбрать между IPv4 и IPv6 используя следующий синтаксис: ### Показывать только TCP/IP IPv4 ## ip -4 a
### Показывать только TCP/IP IPv6 ### ip -6 a Также существует возможность вывести детали только об определенном сетевом интерфейсе: ### Показать только интерфейс eth0 ### ip a show eth0 ip a list eth0 ip a show dev eth0
### Показать только поднятые интерфейсы ### ip link ls up
Таблица выводимых параметров
Чтобы получить информацию о каждом из объектов используйте команду help следующим образом: ip OBJECT help ip OBJECT h ip a help ip r help
Подробнее см. http://debian-help.ru/articles/nastroika-seti-s-pomoschyu-utility-ip-v-debian-linux/
2. Установить SSH-клиент (при необходимости на собственных компьютерах например, putty) Подключиться к серверу, с использованием параметров, полученных ipscan (дополнительные параметры получить у преподавателя)
3. Апробация запуска MPI скриптов на Python Большинство программ MPI могут быть запущены с помощью команды mpiexec. На практике запуск программ Python выглядит так: $ mpiexec -n 4 python script.py ( запустить программу с 4 процессорами)
Знакомство с примерами программ
Задание 1. Написание простейшей программы Hello World для нескольких процессов. Исходный код выглядит следующим образом: #hello.py from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() print "hello world from process ", rank 2-й вариант: #hello_mpi.py from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() size = comm.Get_size() print "hello world from process %d/%d“ %(rank,size)
Запуск несколько попыток. После уяснения смысла предъявить преподаваелю: $ mpiexec -n 5 python hello.py
$interactive –A uoa00243 –c 4 –e “python ./hello_mpi.py”
Предупреждение. Плохой практикой является выполнение ввода-вывода из любого процесса, помимо корневого (например, вызов print). Вывод часто может быть полезным инструментом для отладки. Поясните назначение корневого класса mpi4py class, Comm
Задание (факультативно). Параллельнпя обработка фотографий. Программа denoise_serial.py применяет алгоритм де-шумизации к списку фотографий. Фотографии предлагается подготовить самостоятельно.
import numpy as np from skimage import data, img_as_float from skimage.filter import denoise_bilateral import skimage.io import os.path import time
curPath = os.path.abspath(os.path.curdir) noisyDir = os.path.join(curPath,'noisy') denoisedDir = os.path.join(curPath,'denoised')
def loop(imgFiles): for f in imgFiles: img = img_as_float(data.load(os.path.join(noisyDir,f))) startTime = time.time() img = denoise_bilateral(img, sigma_range=0.1, sigma_spatial=3), skimage.io.imsave(os.path.join(denoisedDir,f), img) print("Took %f seconds for %s" %(time.time() - startTime, f)) def serial(): total_start_time = time.time() imgFiles = ["%.4d.jpg"%x for x in range(1,101)] loop(imgFiles) print("Total time %f seconds" %(time.time() - total_start_time)) if __name__=='__main__': serial()
Задание а (факультативно). Параллельнпя обработка 100 фотографий. import numpy as np
from skimage import data, img_as_float from skimage.filter import denoise_tv_chambolle, denoise_bilateral,denoise_tv_bregman import skimage.io
import os.path import time from mpi4py import MPI from numba import jit
curPath = os.path.abspath(os.path.curdir) noisyDir = os.path.join(curPath,'noisy') denoisedDir = os.path.join(curPath,'denoised')
@jit def loop(imgFiles,rank): for f in imgFiles: img = img_as_float(data.load(os.path.join(noisyDir,f))) startTime = time.time() img = denoise_bilateral(img, sigma_range=0.1, sigma_spatial=3), skimage.io.imsave(os.path.join(denoisedDir,f), img) print ("Process %d: Took %f seconds for %s" %(rank, time.time() - startTime, f)) def parallel(): comm = MPI.COMM_WORLD rank = comm.Get_rank() size = comm.Get_size()
totalStartTime = time.time() numFiles = 100/size #number of files this process will handle imgFiles = ["%.4d.jpg"%x for x in range(rank*numFiles+1, (rank+1)*numFiles+1)] # Fix this line to distribute imgFiles loop(imgFiles,rank)
print "Total time %f seconds" %(time.time() - totalStartTime)
if __name__=='__main__': parallel()
(тестирование на 4-х ядрах) $ interactive –A uoa00243 –c 4 –e “python ./denoise_parallel.py”
Задание 2 (см задание 1. сравнить). Коммуникации точка-точка Источник: A Hands-on Introduction to MPI Python Programming , Sung Bae, Ph.D , New Zealand eScience Infrastructure.
В примере показано применение команд send и recv для коммуникации точка-точка
#hello_p2p.py from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() size = comm.Get_size() if rank == 0: for i in range(1, size): sendMsg = “Hello, Rank %d“ %i comm.send(sendMsg, dest=i) else: recvMsg = comm.recv(source=0) print recvMsg
Пробуем запуск: $interactive –A uoa00243 –c 4 –e “python hello_p2p.py”
Задание 3. COLLECTIVE COMMUNICATION – BROADCAST (Коллективные коммуникации. Трансляция).
#hello_bcast.py from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() size = comm.Get_size() if rank == 0: comm.bcast("Hello from Rank 0", root=0) else: msg=comm.bcast(root=0) print "Rank %d received: %s" %(rank, msg)
Исполнение $interactive –A uoa00243 –c 4 –e “python hello_bcast.py” Задание 4. P2P VS COLLECTIVE – REDUCE. Вычисление суммы в нулевом ранге.
#sum_p2p.py from mpi4py import MPI comm = MPI.COMM_WORLD rank=comm.Get_rank() size=comm.Get_size() val = (rank+1)*10 print "Rank %d has value %d" %(rank, val) if rank == 0: sum = val for i in range(1,size): sum += comm.recv(source=i) print "Rank 0 worked out the total %d" %sum else: comm.send(val, dest=0)
Обратите внимание, что Ранг 0 "receives" от ранга 1, ранга 2 и ранга 3 по-порядку. Каждый процесс стартует “send”, как только процесс запускается на выполнение, но «send» завершится только когда соответсвующий «resv» вызывается Рангом 1.
Наличие такой «sequential» «последовательной» процедуры в параллельном коде не является идеальным. При наличии только 4 процессов это может показаться не очень важным, но это может быть очень неэффективным, когда у нас есть, скажем, 1000 процессов. Передача значений последовательно перевешивает цель параллельного программирования.
from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() size = comm.Get_size() val = (rank+1)*10 print "Rank %d has value %d" %(rank, val) sum = comm.reduce(val, op=MPI.SUM, root=0) if rank==0: print "Rank 0 worked out the total %d" %sum
|
|||||||||||||||||||||||||||||||||||
|