Одни и те же случайные числа для каждого процесса в коде C++ с MPI

У меня есть код C++ MPI, который работает, поскольку он компилируется и действительно запускается на указанном количестве процессоров (n). Проблема в том, что он просто выполняет одно и то же вычисление n раз, а не делает одно вычисление n раз быстрее.

Я взломал довольно много примеров, которые я нашел на разных сайтах, и, похоже, мне не хватает правильного использования MPI_Send и MPI_Receive, но я не могу найти экземпляр этих команд, которые принимают функцию в качестве входных данных (и я сбит с толку относительно почему эти команды MPI могут быть полезны для чего-либо, кроме функций).

Мой код ниже. По сути, он вызывает функцию C++, которую я написал для получения p-значения точного теста Фишера. Бит случайного числа — это то, что я вставил для проверки скорости.

Я хочу, чтобы эта программа выдавала Fisher.TwoTailed с каждым набором случайных переменных (т. е. A, B, < em>C и D) на другой процессор вместо того, чтобы выполнять одни и те же вычисления на нескольких процессорах. Заранее спасибо за любое понимание - ура!

Вот код:

int 
main (int argc, char* argv[]) 
{ 

  int id;
  int p;
//
//  Initialize MPI.
//
  MPI::Init ( argc, argv );
//
//  Get the number of processors.
//
  p = MPI::COMM_WORLD.Get_size ( );
//
//  Get the rank of this processor.
//
 id = MPI::COMM_WORLD.Get_rank ( );

  FishersExactTest Fishers;

  int i = 0;
  while (i < 10) {
    int A = 0 + rand() % (100 - 0);
    int B = 0 + rand() % (100 - 0);
    int C = 0 + rand() % (100 - 0);
    int D = 0 + rand() % (100 - 0); 
    cout << Fishers.TwoTailed(A, B, C, D) << endl;
    i += 1;
  }

  MPI::Finalize ( );
  return 0;
}

person Dave    schedule 10.06.2011    source источник


Ответы (4)


Вам следует пройти базовое обучение параллельным вычислениям и MPI. Одним из хороших ресурсов, который научил меня основам, был бесплатный набор онлайн-курсов, организованных Национальным центром суперкомпьютерных приложений (NCSA).

person Seth Johnson    schedule 10.06.2011

Вы должны сказать MPI, как распараллелить код — он не сделает это автоматически.

Другими словами, вы не можете инициализировать MPI на всех системах, а затем передать им один и тот же цикл. Вы хотите использовать id каждого процессора, чтобы определить, над какой частью цикла он будет работать. Затем вам нужно, чтобы все они передали свои результаты обратно в ID 0.

person i_grok    schedule 10.06.2011

Все вышеперечисленные ответы совершенно верны. Позвольте мне добавить немного:

Здесь, поскольку похоже, что вы просто делаете случайную выборку, все, что вам нужно сделать, чтобы разные процессоры генерировали разные случайные числа для передачи Fishers.TwoTailed, — это убедиться, что все они имеют разные начальные значения для PRNG:

int 
main (int argc, char* argv[]) 
{ 

  int id;
  int p;
//
//  Initialize MPI.
//
  MPI::Init ( argc, argv );
//
//  Get the number of processors.
//
  p = MPI::COMM_WORLD.Get_size ( );
//
//  Get the rank of this processor.
//
 id = MPI::COMM_WORLD.Get_rank ( );

  FishersExactTest Fishers;

  srand(id);  // <--- each rank gets a different seed

  int i = 0;
  while (i < 10) {
    int A = 0 + rand() % (100 - 0);
    int B = 0 + rand() % (100 - 0);
    int C = 0 + rand() % (100 - 0);
    int D = 0 + rand() % (100 - 0); 
    cout << Fishers.TwoTailed(A, B, C, D) << endl;
    i += 1;
  }

  MPI::Finalize ( );
  return 0;
}

Поскольку цикл от 1 до 10, вы все равно получите каждый процесс, выполняющий 10 выборок. Если вы хотите, чтобы они сделали всего 10, вы можете разделить 10 на p и сделать что-то, чтобы распределить остаток: например

int niters = (10+id)/p;
int i=0;
while (i < niters) {
  ...
}
person Jonathan Dursi    schedule 10.06.2011

Итак, какие сообщения вы получаете, когда запускаете задание MPI? Просто чтобы повторить то, что сказали другие, вам нужно будет явно определить, какова работа каждого процессора... например... если у вас ранг 0 (по умолчанию), сделайте это... если у вас ранг 1 и т. д. ..(или другой синтаксис), который определяет роль для каждого ранга. Затем вы могли бы, в зависимости от того, как вы структурируете свой код, иметь узлы Send/Recv, Gather, Scatter и т. д.

person Ashmohan    schedule 10.06.2011
comment
Когда я запускаю этот небольшой фрагмент кода, который я опубликовал, я получаю 10 наборов np идентичных результатов, где np — это количество процессоров, на которых я указываю коду выполняться ( т. е. mpirun -np np MyExe.cc). Но да, похоже, что работа с Send/Recv поможет мне двигаться вперед. Send/Recv принимает такие вещи, как строки, числа с плавающей запятой, целые числа и т. д., тогда как на самом деле мне нужна функция Fishers.TwoTailed(A,B,C,D), переданная отдельным процессорам. . - person Dave; 10.06.2011
comment
Каждый процессор будет выполнять то задание, которое вы ему укажете, поэтому, если вы явно не определите его в своем исходном коде, вы увидите тот же результат. - person Ashmohan; 10.06.2011