В функциях приёма в качестве аргумента типа MPI_Status
можно указывать MPI_STATUS_IGNORE
— в этом случае объявлять отдельную переменную типа MPI_Status не нужно.
Предложенный в прошлой презентации метод с использованием MPI_Type_vector
не работает, т.к. элементы вектора в такой схеме лежат не плотно.
Корректно реализовать такой метод рассылки было бы с использованием MPI_Type_darray
(http://mpi.deino.net/mpi_functions/MPI_Type_create_darray.html).
При разделении по столбцам, если сама матрица при этом хранится по строкам, проще всего рассылать «пакетами» по \(P\) элементов с помощью MPI_Scatter.
Как и раньше, в примере рассмотрен только случай \(N ⋮ P\), для использования в программе нужно модифицировать для случая деления с остатком (например, добавить выравнивание).
double *matrix_buffer = calloc(N*N/P, sizeof(double));
// только в 0-м процессе
double *row_buffer = calloc(N, sizeof(double));
// ...
for (int row=0; row < N; row++) {
// считать/сгенерировать
// строку row размера N в row_buffer
read_row(N, row, row_buffer);
// считать из row_buffer части строки через P элементов
// записать в matrix_buffer подряд
for (int col = 0; col < N; col += P) {
MPI_Scatter(row_buffer+col, 1, MPI_DOUBLE,
0, MPI_COMM_WORLD);
}
}
Для лаконичности кода часто при пересылках «точка-точка» удобно бывает не рассматривать отдельно случай, когда отправитель и получатель — один и тот же процесс (например, при \(P=1\)). В общем случае это не рекомендуется (лучше проверять if-ом). buff1 и buff2 должны быть разными участками памяти.
Источник: http://stackoverflow.com/a/20143164
MPI_Request req;
// Start a non-blocking receive
MPI_Irecv(buff2, count, datatype, sender, 0, comm, &req);
// Send to everyone
MPI_Send(buff1, count, datatype, receiver, 0, comm);
// Complete the non-blocking receive
MPI_Wait(&req, MPI_STATUS_IGNORE);