Это очень похоже на этот вопрос: Как получить столбцы MPI_Gatherv из процессора, где каждый процесс может отправлять различное количество столбцов .Проблема в том, что столбцы не являются смежными в памяти, поэтому вам нужно поиграться.
Как всегда в случае с C, при отсутствии реальных многомерных массивов, вы должны быть немного осторожны с разметкой памяти.Я верю в C, это тот случай, когда статически объявленный массив, такой как
float a[nrows][ncols]
, будет непрерывным в памяти, так что вы должны быть в порядке на данный момент.Однако имейте в виду, что как только вы перейдете к динамическому распределению, это больше не будет иметь место;вам нужно было бы выделить все данные одновременно, чтобы убедиться, что вы получаете непрерывные данные, например,
float **floatalloc2d(int n, int m) {
float *data = (float *)malloc(n*m*sizeof(float));
float **array = (float **)calloc(n*sizeof(float *));
for (int i=0; i<n; i++)
array[i] = &(data[i*m]);
return array;
}
float floatfree2d(float **array) {
free(array[0]);
free(array);
return;
}
/* ... */
float **a;
nrows = 3;
ncols = 2;
a = floatalloc2d(nrows,ncols);
, но я думаю, что вы все в порядке.
Теперь, когда у вас естьВаш 2d массив так или иначе, вы должны создать свой тип.Тип, который вы описали, подходит, если вы просто отправляете один столбец;но хитрость здесь в том, что если вы отправляете несколько столбцов, каждый столбец начинается только на один поток после начала предыдущего, даже если сам столбец охватывает почти весь массив!Поэтому вам нужно переместить верхнюю границу типа, чтобы это работало:
MPI_Datatype col, coltype;
MPI_Type_vector(nrows,
1,
ncols,
MPI_FLOAT,
&col);
MPI_Type_commit(&col);
MPI_Type_create_resized(col, 0, 1*sizeof(float), &coltype);
MPI_Type_commit(&coltype);
будет делать то, что вы хотите.Обратите внимание, что процессы , получающие , будут иметь разные типы, чем процессы , отправляющие , потому что они хранят меньшее количество столбцов;так что шаг между элементами меньше.
Наконец, теперь вы можете сделать разброс,
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
if (rank == 0) {
a = floatalloc2d(nrows,ncols);
sendptr = &(a[0][0]);
} else {
sendptr = NULL;
}
int ncolsperproc = ncols/size; /* we're assuming this divides evenly */
b = floatalloc(nrows, ncolsperproc);
MPI_Datatype acol, acoltype, bcol, bcoltype;
if (rank == 0) {
MPI_Type_vector(nrows,
1,
ncols,
MPI_FLOAT,
&acol);
MPI_Type_commit(&acol);
MPI_Type_create_resized(acol, 0, 1*sizeof(float), &acoltype);
}
MPI_Type_vector(nrows,
1,
ncolsperproc,
MPI_FLOAT,
&bcol);
MPI_Type_commit(&bcol);
MPI_Type_create_resized(bcol, 0, 1*sizeof(float), &bcoltype);
MPI_Type_commit(&bcoltype);
MPI_Scatter (sendptr, ncolsperproc, acoltype, &(b[0][0]), ncolsperproc, bcoltype, 0, MPI_COMM_WORLD);