Синхронизировать массив по процессам MPI: неправильное использование MPI_Allgather?

Я знаю, что подобные вопросы уже обсуждались ранее, см. ниже, почему они не относятся к моему делу. У меня есть кусок кода, который выглядит следующим образом:

int current_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &current_rank);

if (current_rank==ROOT_RANK){
   ...
  #pragma omp for
  for (long i = 0; i < num; i++) {
      auto &choumbie = catalogue->get()[i];
      /* array choumbie is modified */}
   ...}

а затем я хотел бы синхронизировать массив «чумби» по всем процессам. Я попытался реализовать его после этого пример и документацию. Итак, сразу после if (current_rank==ROOT_RANK) я сделал:

  int gsize;
  int *rbuf; // address of receive buffer
  auto &choumbie = catalogue->get();

  MPI_Comm_size(comm, &gsize);
  int send_count=num;
  rbuf = (int*)malloc(gsize*send_count*sizeof(double));
  MPI_Allgather(choumbie,send_count, MPI_DOUBLE, rbuf, send_count, MPI_DOUBLE, comm);

Я думаю, что массив 'choumbie', который я хочу синхронизировать, не входит таким образом, но я также не нашел другого полезного примера. Похоже, что этот первый аргумент должен быть адресом памяти массива, который должен быть отправлен, но это не соответствует приведенному мной примеру выше.

P.S.: число одинаковое для каждого ранга.

Этот вопрос в моем случае не помогло, потому что я хотел бы использовать MPI_Allgather (также на C++, а не на Fortran). Также это не помогло в моем случае, потому что я хотел бы избежать использования MPI_Barrier.


person Suyama87    schedule 25.06.2020    source источник
comment
Одинаково ли число на каждом ранге? rbuf — это целочисленный массив, но вы общаетесь, используя тип MPI_DOUBLE. Возможно, вам потребуется выделить rbuf с глобальной суммой num, используя функцию allreduce.   -  person wvn    schedule 25.06.2020
comment
Да, номер тот же. Я обновил пост соответственно. Не могли бы вы привести пример кода того, что вы имеете в виду? Wrt rbuf, это опечатка, это дубль, тоже исправлено.   -  person Suyama87    schedule 25.06.2020
comment
Я что-то пропустил в вашем исходном коде, вам не понадобится вызов Allreduce. Код для подражания.   -  person wvn    schedule 25.06.2020
comment
Что вы подразумеваете под синхронизацией массива? Если вы хотите, чтобы копия ROOT_RANK распространялась на все остальные ранги, просто используйте MPI_Bcast. С помощью MPI_Allgather вы собираете локальные копии choumbie и объединяете их в один большой массив в rbuf. Или choumbie распределяется по блокам?   -  person Hristo Iliev    schedule 25.06.2020
comment
Я хотел бы собрать информацию со всех рангов до choumbie. Таким образом, независимо от того, каким образом процессы изменили (или не изменили) массив, я хотел бы, чтобы окончательный choumbie был обновлен любыми изменениями, которые он мог претерпеть со всех рангов. Но для всего, что вы предлагаете, не могли бы вы привести примеры кода, потому что проблема в том, что я не понимаю синтаксис в моем контексте в первую очередь.   -  person Suyama87    schedule 25.06.2020
comment
Извините, я действительно не понимаю, что вам нужно. Либо у вас есть куски большого массива, разбросанные по узлам, и вы хотите собрать эти куски после их изменения — легко, делается с помощью MPI_Allgather. Или у вас есть несколько копий одного и того же массива и вы хотите объединить локальные модификации — это совсем не просто, если только модификации не находятся в смежных непересекающихся областях. Судя по принятому ответу, у вас первый случай.   -  person Hristo Iliev    schedule 26.06.2020


Ответы (1)


Пока num одинаково на каждом ранге, это близко. Это зависит от того, что вам дает catalogue->get();. Я собираюсь предположить, что это целочисленный массив. Вам просто нужно:

MPI_Allgather(choumbie,send_count, MPI_INT, rbuf, send_count, MPI_INT, comm);
person wvn    schedule 25.06.2020