Как сделать MPI_Scatter в MPI для всех узлов, кроме корневого?
В MPI, если я выполняю MPI_Scatter для MPI_COMM_WORLD, все узлы получают некоторые данные (включая отправляющий корень).
Как выполнить MPI_Scatter от корневого узла ко всем остальным узлам и убедиться, что корневой узел не получает никаких данных?
Является ли создание нового MPI_Comm, содержащего все узлы, кроме корневого, жизнеспособным подходом?
1 ответ
Давайте представим, что ваш код выглядит так:
int rank, size; // rank of the process and size of the communicator
int root = 0; // root process of our scatter
int recvCount = 4; // or whatever
double *sendBuf = rank == root ? new double[recvCount * size] : NULL;
double *recvBuf = new double[recvCount];
MPI_Scatter( sendBuf, recvCount, MPI_DOUBLE,
recvBuf, recvCount, MPI_DOUBLE,
root, MPI_COMM_WORLD );
Так что здесь, действительно, root
Процесс отправит данные самому себе, хотя этого можно избежать. Вот два очевидных метода, которые приходят на ум, чтобы достичь этого.
С помощьюMPI_IN_PLACE
Призыв к MPI_Scatter()
не пришлось бы менять. Единственным изменением в коде будет определение приемного буфера, который станет примерно таким:
double *recvBuf = rank == root ?
static_cast<double*>( MPI_IN_PLACE ) :
new double[recvCount];
С помощьюMPI_Scatterv()
При этом вам нужно будет определить массив целых чисел, описывающих индивидуальные размеры приема, массив смещений, описывающих начальные индексы, и использовать их в вызове MPI_Scatterv()
который заменит вам звонок MPI_Scatter()
как это:
int sendCounts[size] = {recvCount}; // everybody receives recvCount data
sendCounts[root] = 0; // but the root process
int displs[size];
for ( int i = 0; i < size; i++ ) {
displs[i] = i * recvCount;
}
MPI_Scatterv( sendBuf, sendCounts, displs, MPI_DOUBLE,
recvBuf, recvCount, MPI_DOUBLE,
root, MPI_COMM_WORLD );
Конечно, в обоих случаях не будет данных о приемном буфере для процесса root
и это должно быть учтено в вашем коде.
Я лично предпочитаю первый вариант, но оба работают.