От OpenMP к MPI

Мне просто интересно, как преобразовать следующую программу openMP в программу MPI

#include <omp.h>  
#define CHUNKSIZE 100  
#define N     1000  

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

int i, chunk;  
float a[N], b[N], c[N];  

/* Some initializations */  
for (i=0; i < N; i++)  
  a[i] = b[i] = i * 1.0;  
chunk = CHUNKSIZE;  

#pragma omp parallel shared(a,b,c,chunk) private(i)  
  {  

  #pragma omp for schedule(dynamic,chunk) nowait  
  for (i=0; i < N; i++)  
    c[i] = a[i] + b[i];  

  }  /* end of parallel section */  

return 0;  
}  

У меня есть похожая программа, которую я хотел бы запустить на кластере, и программа использует OpenMP.

Спасибо!


ОБНОВИТЬ:

В следующем игрушечном коде я хочу ограничить параллельную часть внутри функции f():

#include "mpi.h"  
#include <stdio.h>  
#include <string.h>  

void f();

int main(int argc, char **argv)  
{  
printf("%s\n", "Start running!");  
f();  
printf("%s\n", "End running!");  
return 0;  
}  


void f()  
{  
char idstr[32]; char buff[128];  
int numprocs; int myid; int i;  
MPI_Status stat;  

printf("Entering function f().\n");

MPI_Init(NULL, NULL);  
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);  
MPI_Comm_rank(MPI_COMM_WORLD,&myid);  

if(myid == 0)  
{  
  printf("WE have %d processors\n", numprocs);  
  for(i=1;i<numprocs;i++)  
  {  
    sprintf(buff, "Hello %d", i);  
    MPI_Send(buff, 128, MPI_CHAR, i, 0, MPI_COMM_WORLD); }  
    for(i=1;i<numprocs;i++)  
    {  
      MPI_Recv(buff, 128, MPI_CHAR, i, 0, MPI_COMM_WORLD, &stat);  
      printf("%s\n", buff);  
    }  
}  
else  
{  
  MPI_Recv(buff, 128, MPI_CHAR, 0, 0, MPI_COMM_WORLD, &stat);  
  sprintf(idstr, " Processor %d ", myid);  
  strcat(buff, idstr);  
  strcat(buff, "reporting for duty\n");  
  MPI_Send(buff, 128, MPI_CHAR, 0, 0, MPI_COMM_WORLD);  
}  
MPI_Finalize();  

printf("Leaving function f().\n");  
}  

Тем не менее, текущий вывод не ожидается. Части printf до и после выполнения параллельной части каждым процессом, а не только основным процессом:

$ mpirun -np 3 ex2  
Start running!  
Entering function f().  
Start running!  
Entering function f().  
Start running!  
Entering function f().  
WE have 3 processors  
Hello 1 Processor 1 reporting for duty  

Hello 2 Processor 2 reporting for duty  

Leaving function f().  
End running!  
Leaving function f().  
End running!  
Leaving function f().  
End running!  

Так что мне кажется, что параллельная часть не ограничена между MPI_Init() и MPI_Finalize().


person Tim    schedule 28.01.2010    source источник


Ответы (3)


Чтобы ответить на ваше обновление:

При использовании MPI каждый процессор выполняет одну и ту же программу. Чтобы ограничить параллельные части, вам нужно будет использовать такой оператор, как:

if (rank == 0) { ...serial work... }

Это гарантирует, что внутри этого блока работает только один процессор.

Вы можете увидеть, как это работает, в примере программы, который вы опубликовали, внутри f() есть оператор if(myid == 0). Этот блок операторов затем будет выполняться только процессом 0, все остальные процессы переходят прямо к else и получают свои сообщения, прежде чем отправить их обратно.

Что касается MPI_Init и MPI_Finalize -- MPI_Init инициализирует среду MPI. После того, как вы вызвали этот метод, вы можете использовать другие методы MPI, такие как Send и Recv. Как только вы закончите использовать методы MPI, MPI_Finalize освободит ресурсы и т. д., но программа продолжит работу. Например, вы можете вызвать MPI_Finalize перед выполнением некоторого ввода-вывода, который займет много времени. Эти методы не ограничивают параллельную часть кода, а только то, где вы можете использовать другие вызовы MPI.

Надеюсь это поможет.

person davidb    schedule 24.02.2011

Вам просто нужно назначить часть массивов (a, b, c) каждому процессу. Что-то вроде этого:

#include <mpi.h>

#define N 1000

int main(int argc, char *argv[])
{
  int i, myrank, myfirstindex, mylastindex, procnum;
  float a[N], b[N], c[N];

  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &procnum);
  MPI_Comm_rank(comm, &myrank);


  /* Dynamic assignment of chunks,
   * depending on number of processes
   */
  if (myrank == 0)
    myfirstindex = 0;
  else if (myrank < N % procnum)
    myfirstindex = myrank * (N / procnum + 1);
  else
    myfirstindex = N % procnum + myrank * (N / procnum);

  if (myrank == procnum - 1)
    mylastindex = N - 1;
  else if (myrank < N % procnum)
    mylastindex = myfirstindex + N / procnum + 1;
  else
    mylastindex = myfirstindex + N / procnum;

  // Initializations
  for(i = myfirstindex; i < mylastindex; i++)  
    a[i] = b[i] = i * 1.0; 

  // Computations
  for(i = myfirstindex; i < mylastindex; i++)
    c[i] = a[i] + b[i];

  MPI_Finalize();
}
person 3lectrologos    schedule 28.01.2010
comment
Спасибо, 3lectrologos! Моя реальная проблема немного сложнее. Я указал это в stackoverflow.com/questions/2156714/. Взгляни, пожалуйста. Заранее спасибо. - person Tim; 28.01.2010
comment
Спасибо, 3lectrologos! Я только что добавил несколько обновлений к своим вопросам, чтобы показать, что кажется неверным, что параллельная часть начинается с MPI_Init и заканчивается MPI_Finalize. - person Tim; 29.01.2010

Можно попробовать использовать проприетарный Intel Cluster OpenMP. Он будет запускать программы OpenMP на кластере. Да, он имитирует компьютер с общей памятью в кластерах с распределенной памятью, используя «программную распределенную общую память» http://en.wikipedia.org/wiki/Distributed_shared_memory

Он прост в использовании и включен в компилятор Intel C++ (9.1+). Но работает только на 64-битных процессорах.

person osgx    schedule 01.02.2010