Тип данных MPI для массива 2 d - PullRequest
3 голосов
/ 16 апреля 2010

Мне нужно передать массив целочисленных массивов (в основном массив 2 d) всем процессорам от root. Я использую MPI в программах на Си.Как объявить тип данных MPI для массива 2 d и как отправить сообщение (использовать широковещательную рассылку или рассылку)

Ответы [ 4 ]

12 голосов
/ 16 апреля 2010

Вам нужно будет использовать 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 имеет (незначительно) меньше кода и дает тот же результат.

3 голосов
/ 16 апреля 2010

Если вы отправляете непрерывный блок данных (я думаю, что массивы C непрерывны, но я программист на Фортране и не очень уверен), вам не нужно объявлять новый тип данных MPI, хотя есть некоторые причины почему вы можете захотеть. Рассеяние предназначено для распределения, скажем, массива по нескольким процессам; Вы можете использовать scatter для отправки каждой строки массива в другой процесс. Так что для вашего примера непрерывного массива целых чисел ваш самый простой вариант - вещать, как это (имея в виду мои плохие навыки C):

MPI_Bcast(&buf, numRows*numCols, MPI_INT, root, MPI_COMM_WORLD)

, где

&buf - адрес первого элемента в массиве

numRows*numCols - это, конечно, количество элементов в двумерном массиве

MPI_INT (вероятно) является внутренним типом данных, который вы будете использовать

root - ранг процесса, передающего массив

MPI_COMM_WORLD - обычный коммуникатор по умолчанию, при необходимости измените

И не забывайте, что вещание - это коллективная операция, все процессы выполняют один и тот же вызов.

Если ваш массив не является смежным, повторите публикацию с некоторыми размерами массивов образцов, и мы выясним, как определить тип данных MPI.

0 голосов
/ 31 мая 2011
MPI_Send(tempmat,16,MPI_INT,0,0,MPI_COMM_WORLD);

MPI_Recv(resultmaster,16,MPI_INT,MPI_ANY_SOURCE , 0, MPI_COMM_WORLD, &stat);

Я получаю только первый ряд матрицы при использовании вышеуказанных API.

0 голосов
/ 16 апреля 2010

Ваш массив массивов не может быть напрямую передан другому процессу, потому что виртуальные адреса могут отличаться;то есть первый размерный массив с указателями на другие массивы не будет иметь смысла ни для какого другого процесса.Поэтому вы должны передать каждый массив отдельно и вручную собрать свой «2d массив» на стороне получателя.

2) Broadcast vs. Scatter.Broadcast отправляет полный массив во все другие ранги MPI в коммуникаторе.Скаттер, OTOH, распределяет исходный массив по всем другим рангов MPI.Т.е. с трансляцией каждый ранг получает копию исходного массива, а с разбросом каждый ранг получает различную часть массива.

...