Синхронизиране на масив през 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 */}
   ...}

и след това бих искал да синхронизирам масива "choumbie" през всички процеси. Опитах се да го внедря след това пример и документация. И така, веднага след 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