Как сделать 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 и это должно быть учтено в вашем коде.

Я лично предпочитаю первый вариант, но оба работают.

Другие вопросы по тегам