Вам нужно будет использовать Broadcast , потому что вы хотите отправлять копии одного и того же сообщения каждому процессу. Scatter разбивает сообщение и распределяет порции по процессам.
Что касается отправки данных: тип данных HIndexed для вас.
Предположим, ваш 2d массив определен так:
int N; // number of arrays (first dimension)
int sizes[N]; // number of elements in each array (second dimensions)
int* arrays[N]; // pointers to the start of each array
Сначала вам нужно вычислить смещение начального адреса каждого массива относительно начального адреса типа данных, который может быть начальным адресом первого массива, чтобы сделать вещи удобными:
MPI_Aint base;
MPI_Address(arrays[0], &base);
MPI_Aint* displacements = new int[N];
for (int i=0; i<N; ++i)
{
MPI_Address(arrays[i], &displacements[i]);
displacements[i] -= base;
}
Тогда определение для вашего типа будет:
MPI_Datatype newType;
MPI_Type_hindexed(N, sizes, displacements, MPI_INTEGER, &newType);
MPI_Type_commit(&newType);
Это определение создаст тип данных, который содержит все ваши массивы, упакованные один за другим. После этого вы просто отправляете свои данные как один объект этого типа:
MPI_Bcast(arrays, 1, newType, root, comm); // 'root' and 'comm' is whatever you need
Однако вы еще не закончили. Процессы получения должны знать размеры массивов, которые вы отправляете: если эти знания не доступны во время компиляции, вам сначала нужно отправить отдельное сообщение с этими данными (простой массив целых чисел). Если N
, sizes
и arrays
определены так же, как и выше для принимающих процессов, с достаточным пространством, выделенным для заполнения массивов, то все принимающие процессы должны определить один и тот же тип данных (точно такой же код, как отправитель), а затем получить сообщение отправителя как один экземпляр этого типа:
MPI_Bcast(arrays, 1, newType, root, comm); // 'root' and 'comm' must have the same value as in the sender's code
И вуаля! У всех процессов теперь есть копия вашего массива.
Конечно, все станет намного проще, если 2-е измерение вашего 2d-массива будет зафиксировано на некотором значении M
. В этом случае самое простое решение - просто сохранить его в одном массиве int[N*M]
: C ++ гарантирует, что это вся непрерывная память, поэтому вы можете транслировать ее без определения пользовательского типа данных, например:
MPI_Bcast(arrays, N*M, MPI_INTEGER, root, comm);
Примечание: вы могли бы сойтись с использованием Indexed type вместо HIndexed. Разница в том, что в Indexed массив displacements
задается в количестве элементов, в то время как в HIndexed это число байтов (H обозначает гетерогенный). Если бы вы использовали Indexed, то значения, указанные в displacements
, должны были бы быть разделены на sizeof(int)
. Однако я не уверен, что целочисленные массивы, определенные в произвольных позициях в куче, гарантированно «выстраиваются» до целочисленных пределов в C ++, и в любом случае версия HIndexed имеет (незначительно) меньше кода и дает тот же результат.