- •Федеральное агентство по атомной энергии
- •Национальный исследовательский ядерный университет «мифи»
- •Средства разработки параллельных приложений на общей и распределенной памяти в стандарте интерфейса передачи данных mpi и openmp c реализации курс лекций
- •Void main(int argc, char *argv[] ){
- •Int rank, size;
- •Int mpi_Send(void* buf, int count, mpi_Datatype datatype, int dest, int tag, mpi_Comm comm)
- •Int mpi_Get_count(mpi_Status *status, mpi_Datatype datatype, int *count)
- •Стандартный режим передачи
- •Буферизующий режим передачи
- •1. Барьерная синхронизация - mpi_Barrier (comm)
- •2. Широковещательная передача
- •3. Сбор данных
- •4. Рассылка данных
- •5. Операции редукции (обработки данных)
- •Непрерывный.
- •2. Вектор
- •Int mpi_Type_hvector(int count, int blocklength, int stride, mpi_Datatype oldtype,
- •4. Индексированные данные
- •6. Структурный
- •3. Mpi_Group_translate_ranks (mpi_Group group1, int n, int *ranks1, mpi_Group group2, int *ranks2)
- •4. Mpi_Group _compare(group1, group2, result)
- •6. Mpi_Group _excl(group, n, ranks, newgroup)
- •1. Mpi_Comm_size (comm, size)
- •2. Mpi_Comm_rank(comm, rank)
- •3. Mpi_Comm_compare(comm1, comm2, result)
- •1. Mpi_Comm_dup(comm, newcomm)
- •2. Mpi_Comm_create(comm, group, newcomm)
- •3. Mpi_Comm_split(comm, color, key, newcomm)
- •1. Mpi_Cart_create(mpi_Comm comm_old, int ndims, int *dims, int *periods, int reorder, mpi_Comm *comm_cart)
- •2. Mpi_Dims_create(int nnodes, int ndims, int *dims)
- •1. Mpi_Cartdim_get(mpi_Comm comm, int *ndims)
- •2. Mpi_Cart_get(mpi_Comm comm, int maxdims, int *dims, int *periods, int *coords)
- •3. Int mpi_Cart_rank(mpi_Comm comm, int *coords, int *rank)
- •4. Int mpi_Cart_coords(mpi_Comm comm, int rank, int maxdims, int *coords)
- •5. Координаты декартова сдвига
- •Int mpi_Graph_create(mpi_Comm comm_old, int nnodes, int *index, int *edges, int reorder, mpi_Comm *comm_graph)
- •Int mpi_Topo_test(mpi_Comm comm, int *status)
- •Default(shared | none)
- •Void main()
- •Void main()
- •Int a[10], b[10], c[10]; // целочисленные массивы
- •2. Оператор sections
- •3. Оператор single
- •Void main()
- •10. Функция omp_get_nested
- •Int omp_get_nested(void)
Void main(int argc, char *argv[] ){
Int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
printf("rank=%d\n",rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
printf("size=%d\n",size);
MPI_Finalize();
}
Типы данных MPI
При выполнении операций передачи сообщений в функциях MPI необходимо указывать тип пересылаемых данных. MPI содержит набор базовых типов данных, во многом совпадающих с типами данных в алгоритмических языках C и Fortran. Кроме того, в MPI содержит функции для создания производных типов данных. Все типы данных MPI содержатся в файле mpi.h Аналогично функциям MPI, базовые типы данных имеют префикс MPI, например, MPI_INT, MPI_DOUBLE и т.д. В стандарте MPI не предусмотрен механизм преобразование типов данных, используемый в Си.
При выполнении передачи данных между процессами определяется буфер передачи данных и буфер приема данных. В операциях обмена указывается количество передаваемых/принимаемых данных в единицах данных и тип этих данных. На основании этой информации формируется буфер обмена, размер которого равен числу элементов, умноженному на размер типа данных в байтах. Если в принимающем процессе определить другой тип, что произойдет? Данные будут получены при достаточном размере приемного буфера, но получить правильное значение полученных данных будет проблематично.
При выполнении операций обмена типы данных типы переданных и полученных данных должны совпадать.
Двухточечные обмены
Передача и прием сообщений процессами являются основным механизмом MPI. Основные операции двухточечных обменов это - send и receive. В MPI реализовано два типа обменов, блокирующие обмены и не блокирующие обмены, в каждом из двух типов может использоваться 4 режима связи: стандартный, буферизующий(B), синхронный (S), по готовности (R).
Блокирующие обмены.
M
PI_Send()
M
PI_Bsend()
MPI_Recv()
M
PI_Ssend()
MPI_Rsend()
Для всех режимов передачи используется одна функция приема MPI_Recv.
Функция передачи – стандартный режим:
Int mpi_Send(void* buf, int count, mpi_Datatype datatype, int dest, int tag, mpi_Comm comm)
Функция приема:
int MPI_Recv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
OUT |
buf |
адрес буфера передачи/приема |
IN |
count |
количество элементов в буфере передачи/приема |
IN |
datatype |
тип передаваемых/принимаемых данных |
IN |
dest/source |
ранг (номер процесса) источника (куда/от кого) |
IN |
tag |
тэг сообщения (integer) |
IN |
comm |
коммуникатор |
OUT |
status |
объект статуса (Status) |
Служебная информация однозначно определяет каждое передаваемое и принимаемое сообщение, именно по служебной информации процессы знают, куда и какую информацию необходимо послать, а принимающие процессы знают, от кого должны получить эту информацию.
Tag – это целое число, которое является отличительным признаком сообщения. Если на одном процессе несколько операций передачи сообщения (как у нас, на 0-вом процессе), то они не могут иметь одинаковый tag.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Send процесс 0 -> Recv остальные процессы
// mpirun –np <кол-во_процессов> <имя_исполняемого_файла>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <mpi.h>
#include <iostream>
using namespace std;
void main( int argc, char *argv[] )
{
int proc, size;
MPI_Status stat[2];
MPI_Init( &argc, &argv);
MPI_Comm_rank( MPI_COMM_WORLD, &proc);
MPI_Comm_size( MPI_COMM_WORLD, &size);
double b[10];
if (proc == 0) /* код для процесса с номером 0*/
{
double a[10];
for(int i=0; i<10; i++)
a[i]=(double)proc;
for(i=1; i<size; i++){ /*передача массива */
MPI_Send(&a[0], 10, MPI_DOUBLE, i, 100, MPI_COMM_WORLD);
}
}
else /* код для остальных процессов */
{ /* прием массива на остальных процессах */
MPI_Recv(&b[0], 10, MPI_DOUBLE, 0, 100, MPI_COMM_WORLD, &stat[0]);
for(i=0; i<10; i++)
cout<<b[i]<<”\t|;
}
MPI_Finalize();
}
Возвращаемая статусная информация
MPI_Status - это структура, которая содержит три поля:
MPI_SOURCE,
MPI_TAG,
MPI_ERROR.
Следовательно, status.MPI_SOURCE, status.MPI_TAG и status.MPI_ERROR содержат: ранк источника, тэг и код ошибки принятого сообщения.
Аргумент status также возвращает информацию о длине принятого сообщения. Так как, эта информация не является полем структуры status, то чтобы получить значение длины сообщения нужно вызвать функцию MPI_GET_COUNT.
