Lect_3_131015 (811480), страница 2
Текст из файла (страница 2)
Return code= %d\n", rc);MPI_Finalize(); }dest=1;rc = MPI_Bsend(data, NELEM, MPI_DOUBLE, dest, tag,MPI_COMM_WORLD);printf("Sent message1. Return code= %d\n",rc);Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 322MPI_Buffer_attachdest=2;rc = MPI_Bsend(data, NELEM, MPI_DOUBLE, dest, tag,MPI_COMM_WORLD);printf("Sent message2. Return code= %d\n",rc);MPI_Buffer_detach(&buffer, &size);free (buffer); }else{source=0;MPI_Recv(data, NELEM, MPI_DOUBLE, source, tag,MPI_COMM_WORLD, &status); printf("Received message.
Return code=%d\n",rc);}Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 323Standard send (MPI_Send)Критерий завершения: Не предопределенЗавершается, когда сообщение отосланоМожно предполагать, что сообщение достигло адресатаЗависит от реализацииСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 324Ready send (MPI_Rsend)Критерий завершения: завершается немедленно, ноуспешно только в том случае, если процесс-получательвыставил receiveПреимущество: немедленное завершениеНедостатки: необходимость синхронизацииПотенциально хорошая производительностьСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 325DeadlocksПроцесс 0 посылает большое сообщение процессу 1 Если в принимающем процессе недостаточно места всистемном буфере, процесс 0 должен ждать покапроцесс 1 не предоставит необходимый буфер.•Что произойдет:Process 0Process 1Send(1)Recv(1)Send(0)Recv(0)Называется “unsafe” потому, что зависит от системногобуфера.Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 32626Пути решения «ubsafe» передачУпорядочить передачи:Process 0Process 1Send(1)Recv(1)Recv(0)Send(0)• Использовать неблокирующие передачи:Process 0Process 1Isend(1)Irecv(1)WaitallIsend(0)Irecv(0)WaitallСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 32727Deadlock/* simple deadlock */#include <stdio.h>#include <mpi.h>void main (int argc, char **argv) {int myrank;MPI_Status status;double a[100], b[100];MPI_Init(&argc, &argv); /* Initialize MPI */MPI_Comm_rank(MPI_COMM_WORLD, &myrank); /* Get rank */if( myrank == 0 ) {/* Receive, then send a message */MPI_Recv( b, 100, MPI_DOUBLE, 1, 19, MPI_COMM_WORLD, &status );MPI_Send( a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD );}else if( myrank == 1 ) {/* Receive, then send a message */MPI_Recv( b, 100, MPI_DOUBLE, 0, 17,MPI_COMM_WORLD, &status );MPI_Send( a, 100, MPI_DOUBLE, 0, 19,MPI_COMM_WORLD );} MPI_Finalize(); /* Terminate СпецкурсMPI */ }"Параллельное программированиедля высокопроизводительных систем",Лекция 328Без Deadlock/* safe exchange */#include <stdio.h>#include <mpi.h>void main (int argc, char **argv) {int myrank;MPI_Status status;double a[100], b[100];MPI_Init(&argc, &argv); /* Initialize MPI */MPI_Comm_rank(MPI_COMM_WORLD,&myrank); /* Get rank */if( myrank == 0 ) {MPI_Recv( b, 100, MPI_DOUBLE, 1, 19,MPI_COMM_WORLD, &status );MPI_Send( a, 100, MPI_DOUBLE, 1, 17,MPI_COMM_WORLD );}else if( myrank == 1 ) { /* Send a message, then receive one */MPI_Send( a, 100, MPI_DOUBLE, 0, 19,MPI_COMM_WORLD );MPI_Recv( b, 100, MPI_DOUBLE, 0, 17,MPI_COMM_WORLD, &status );Спецкурс"Параллельноепрограммирование} MPI_Finalize(); /* TerminateMPI*/ }для высокопроизводительных систем",Лекция 329Без Deadlock, но зависит от реализации/* depends on buffering */#include <stdio.h>#include <mpi.h>void main (int argc, char **argv) {int myrank;MPI_Status status;double a[100], b[100];MPI_Init(&argc, &argv); /* Initialize MPI */MPI_Comm_rank(MPI_COMM_WORLD, &myrank); /* Get rank */if( myrank == 0 ) {/* Send a message, then receive one */MPI_Send( a, 100, MPI_DOUBLE, 1, 17, MPI_COMM_WORLD );MPI_Recv( b, 100, MPI_DOUBLE, 1, 19, MPI_COMM_WORLD, &status );}else if( myrank == 1 ) {/* Send a message, then receive one */MPI_Send( a, 100, MPI_DOUBLE, 0, 19, MPI_COMM_WORLD );MPI_Recv( b, 100, MPI_DOUBLE, 0, 17, MPI_COMM_WORLD, &status );}MPI_Finalize(); /* Terminate MPI */}Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 330Совмещение посылки и приемасообщенийДля обмена сообщениями MPI обеспечивает функции:int MPI_Sendrecv(void *sendbuf, int sendcount,MPI_Datatype senddatatype, int dest, int sendtag, void *recvbuf,int recvcount, MPI_Datatype recvdatatype, int source, int recvtag,MPI_Comm comm, MPI_Status *status)Если использовать один буфер:int MPI_Sendrecv_replace(void *buf, int count,MPI_Datatype datatype, int dest, int sendtag,int source, int recvtag, MPI_Comm comm,MPI_Status *status)Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 331Блокирующие и неблокирующие передачиБлокирующие: возврат из функций передачи сообщенийтолько по завершению коммуникацийНеблокирующие (асинхронные): немедленный возврат изфункций, пользователь должен контролировать завершениепередачСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 332Неблокирующие коммуникацииЦель – уменьшение времени работы параллельнойпрограммы за счет совмещения вычислений и обменов.Неблокирующие операции завершаются, не дожидаясьокончания передачи данных.
В отличие от аналогичныхблокирующих функций изменен критерий завершенияопераций – немедленное завершение.Проверка состояния передач и ожидание завершениепередач выполняются специальными функциями.Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 333Неблокирующие функцииNon-Blocking OperationMPI функцииStandard sendMPI_IsendSynchronous sendMPI_IssendBuffered sendMPI_IbsendReady sendMPI_IrsendReceiveMPI_Irecv“I” : ImmediateСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 334Параметры неблокирующихоперацийDatatypeТип MPI_DatatypeCommunicatorАналогично блокирующим (тип MPI_Comm)RequestТипMPI_RequestПараметр request задается при инициации неблокирующейоперацииИспользуется для проверки завершения операцииСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 335Совмещение блокирующих инеблокирующих операцийSend и receive могут блокирующими инеблокирующимиБлокирующий send может соответствоватьнеблокирующему receive, и наоборот, например,MPI_IsendMPI_RecvНеблокирующий send может быть любого типа –synchronous, buffered, standard, readyСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 336Форматы неблокирующих функцийMPI_Isend(buf,count,datatype,dest,tag,comm,request)MPI_Irecv(buf,count,datatype,source,tag,comm, request)request – “квитанция» о завершении передачи.Тип: MPI_RequsetMPI_REQUEST_NULL – обнулениеMPI_Wait() ожидание завершения.MPI_Test() проверка завершения.
Возвращается флаг, указывающий нарезультат завершения.Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 337Неблокирующийsendint MPI_Isend (void *buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm,MPI_Request *request)Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 338Неблокирующийreceiveint MPI_Irecv (void *buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm,MPI_Request *request)Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 339Wait/Test функцииint MPI_Wait(MPI_Request *request,MPI_Status*status)Блокирует процесс до завершения передачи поrequest. В случае успешного завершенияrequest устанавливается в MPI_REQUEST_NULL.Информация по завершившейся передаче – в status.int MPI_Test(MPI_Request *request,int *flag,MPI_Status *status)flag – true, если передача завершилась.Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 340Множественные проверкиTest или wait для завершения одной (и только одной) передачи:– int MPI_Waitany (…)– int MPI_Testany (…)Test или wait завершения всех передач:– int MPI_Waitall (…)– int MPI_Testall (…)Test или wait завершения всех возможных к данному моменту:– int MPI_Waitsome(…)– int MPI_Testsome(…)Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 341СвойстваСохраняется упорядоченность передач, задаваемая порядкомвызовов асинхронных функцийГарантируется завершение соответствующей асихроннойпередачиСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 342Пример использования асинхронныхпередачMPI_Comm_rank(MPI_COMM_WORLD, &myrank); /* find rank */if (myrank == 0) {int x;MPI_Isend (&x,1,MPI_INT, 1, msgtag, MPI_COMM_WORLD, &req1);compute();MPI_Wait (&req1, &status);} else if (myrank == 1) {int x;MPI_Recv (&x,1,MPI_INT,0,msgtag, MPI_COMM_WORLD, &status);}Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 343Коллективные передачиПередача сообщений между группой процессовВызываются ВСЕМИ процессами в коммуникатореПримеры: Broadcast, scatter, gather (рассылка данных) Global sum, global maximum, и т.д.
(Коллективныеоперации) Барьерная синхронизацияСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 344Функции коллективных передачСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 345Характеристики коллективных передачКоллективные операции не являются помехой операциям типа«точка-точка» и наоборотВсе процессы коммуникатора должны вызывать коллективнуюоперациюСинхронизация не гарантируется (за исключением барьера)Нет неблокирующих коллективных операций (MPI-2)Нет тэговПринимающий буфер должен точно соответствовать размеруотсылаемого буфераСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 346Барьерная синхронизацияПриостановка процессов до выхода ВСЕХ процессовкоммуникатора в заданную точку синхронизацииint MPI_Barrier (MPI_Comm comm)Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 347Широковещательная рассылкаOne-to-all передача: один и тот же буфер отсылается отпроцесса root всем остальным процессам в коммуникатореint MPI_Bcast (void *buffer, int, count,MPI_Datatype datatype,int root, MPI_Comm comm)Все процессы должны указать один тот же root и communicatorСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 348ScatterOne-to-all communication: различные данные из одногопроцесса рассылаются всем процессам коммуникатора (впорядке их номеров)int MPI_Scatter(void* sendbuf, int sendcount,MPI_Datatype sendtype, void* recvbuf,int recvcount,MPI_Datatype recvtype, int root,MPI_Comm comm)sendcount – число элементов, посланных каждому процессу, необщее число отосланных элементов;send параметры имеют смысл только для процесса rootСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 349Scatter – графическая иллюстрацияABCDEABCDEABCСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 3DE50GatherAll-to-one передачи: различные данные собираются процессомrootСбор данных выполняется в порядке номеров процессовДлина блоков предполагается одинаковой, т.е.
данные,посланные процессом i из своего буфера sendbuf, помещаютсяв i-ю порцию буфера recvbuf процесса root. Длина массива, вкоторый собираются данные, должна быть достаточной для ихразмещения.int MPI_Gather(void* sendbuf, int sendcount,MPI_Datatype sendtype,void* recvbuf, int recvcount, MPI_Datatype recvtype,int root, MPI_Comm comm)Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 351Gather – графическая илюстрацияABCDECDEABCDEABСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 352Глобальные операции редукцииОперации выполняются над данными, распределенными попроцессам коммуникатораПримеры: Глобальная сумма или произведение Глобальный максимум (минимум) Глобальная операция, определенная пользователемСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 353Общая формаint MPI_Reduce(void* sendbuf, void* recvbuf,int count, MPI_Datatype datatype, MPI_Op op,int root,MPI_Comm comm)•••count число операций “op” выполняемых надпоследовательными элементами буфера sendbuf(также размер recvbuf)op является ассоциативной операцией, котораявыполняется над парой операндов типа datatypeи возвращает результат того же типаСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 354Предопределенные операции редукцииMPI NameMPI_MAXMPI_MINMPI_SUMMPI_PRODMPI_LANDMPI_BANDMPI_LORMPI_BORMPI_LXORMPI_BXORMPI_MAXLOCMPI_MINLOCFunctionMaximumMinimumSumProductLogical ANDBitwise ANDLogical ORBitwise ORLogical exclusive ORBitwise exclusive ORMaximum andlocationMinimum and locationСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 355MPI_ReduceСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 356Варианты MPI_REDUCE•MPI_ALLREDUCE - нет root процесса (все получают рез-т)•MPI_REDUCE_SCATTERMPI_SCAN - “parallel prefix”•Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 357MPI_ALLREDUCEСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 358MPI_REDUCE_SCATTERСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 359MPI_SCANСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 360Коллективные операции редукцииТипы данных, используемых в редукционныхоперациях MPI_MAXLOC и MPI_MINLOC .MPI DatatypeC DatatypeMPI_2INTpair of intsMPI_SHORT_INTshort and intMPI_LONG_INTlong and intMPI_LONG_DOUBLE_INTlong double and intMPI_FLOAT_INTfloat and intMPI_DOUBLE_INTdouble and intСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 361MPI_ALLTOALLint MPI_Alltoall( void* sendbuf,int sendcount,MPI_Datatype sendtype,void* recvbuf,int recvcount,MPI_Datatype recvtype,MPI_Comm comm);/* in *//* in *//* out *//* in *//* in */Описание: Рассылка сообщений от каждого процесса каждому j-ый блок данных из процесса i принимается j-ымпроцессом и размещается в i-ом блоке буфераrecvbufСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 362MPI_ALLTOALLСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 363Пример: вычисление PI (1)#include "mpi.h"#include <math.h>int main(int argc, char *argv[]){int done = 0, n, myid, numprocs, i, rc;double PI25DT = 3.141592653589793238462643;double mypi, pi, h, sum, x, a;MPI_Init(&argc,&argv);MPI_Comm_size(MPI_COMM_WORLD,&numprocs);MPI_Comm_rank(MPI_COMM_WORLD,&myid);while (!done) {if (myid == 0) {printf("Enter the number of intervals: (0 quits) ");scanf("%d",&n);}MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);if (n == 0) break;Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 364Пример: PI (2)h = 1.0 / (double) n;sum = 0.0;for (i = myid + 1; i <= n; i += numprocs) {x = h * ((double)i - 0.5);sum += 4.0 / (1.0 + x*x);}mypi = h * sum;MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0,MPI_COMM_WORLD);if (myid == 0)printf("pi is approximately %.16f, Error is %.16f\n",pi, fabs(pi - PI25DT));}MPI_Finalize();return 0;}Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 365Замер времени MPI_WtimeВремя замеряется в секундахВыделяется интервал в программеdouble MPI_Wtime(void);Пример.double start, finish, elapsed, time ;start=-MPI_Wtime;MPI_Send(…);finish = MPI_Wtime();time= start+finish;Спецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 366Задание 1.Программа на MPI.Реализовать функцию:int MY_Bcast(double *x_send, double *x_recv, int root) – рассылка значенияx_send из процесса root по всем процессам программы.Использовать только функции точка-точка.Время работы замерять функцией MPI_Wtime().Построить график зависимости времени выполнения программы длязаданного файла от числа процессов.Формат отчета – будет уточнен.Отчет в электронном видеСпецкурс "Параллельное программированиедля высокопроизводительных систем",Лекция 367.