понедельник, 25 марта 2013 г.

Основы MPI

Что такое MPI? Смотрим википедию. Здесь же мы придержимся нашего жанра "шпоргалки".
Шесть "главных" MPI команд:
  • MPI_Init(int *argc, char ***argv)
  • MPI_Finalize()
  • MPI_Comm_size(MPI_Comm comm, int *size)
  • MPI_Comm_rank(MPI_Comm comm, int *rank)
  • MPI_Get_processor_name(char *name, int *resultlen)
  • MPI_Send(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
  • MPI Recv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
Основные понятия MPI:
  • типы MPI:
    MPI_CHAR, MPI_SHORT, MPI_INT, MPI_LONG, MPI_UNSIGNED_CHAR, MPI_UNSIGNED_SHORT, MPI_UNSIGNED, MPI_UNSIGNED_LONG, MPI_FLOAT, MPI_DOUBLE, MPI_LONG_DOUBLE
  • MPI коммуникатор
  • MPI tag
  • MPI Processes
Проиллюстрируем это обилие информации классическим приветствием миру. Создаем файл helloworld.c следующего содержания:
#include
#include
int main(int argc, char ** argv) {
    int size,rank;
    int length;
    char name[80];

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Comm_size(MPI_COMM_WORLD,&size);
    MPI_Get_processor_name(name,&length);
    printf("Hello MPI! Process %d of %d on %s\n",size,rank,name);
    MPI_Finalize();
    return 0;
}
Компилируем и запускаем на выполнение:
#mpicc helloworld.c -o helloworld
#mpirun -np 2 ./helloworld
Запустить на выполнение можно так:
#mpirun -np 2 -machinefile hostfile ./helloworld
где hostfile - файл с таким, например, содержанием:
aa slots=4
bb slots=4
cc slots=4

(взято с мануала к команде mpirun) aa, bb, cc - имена узлов. Поварируйте число после ключа -np, узнаете много интересного.
Рассмотрим передачу сообщений между процессами. Отредактируем файл helloworld.c следующим образом:
#include
#include
int main(int argc, char ** argv) {
    int size,rank;
    int length;
    char name[80];
    int dest = 0;
    int tag = 999;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Comm_size(MPI_COMM_WORLD,&size);
    MPI_Get_processor_name(name,&length);
    printf("Hello MPI! Process %d of %d on %s\n",size,rank,name);
    if (rank != 0 ) { /* I’m a client */
        MPI_Send(name,80,MPI_CHAR,dest,tag,MPI_COMM_WORLD);
    }else{ /* I’m the server (rank == 0) */
        MPI_Status status;
        int source;
        for(source = 1; source < size; source++) {
 
MPI_Recv(name,80,MPI_CHAR,source,tag,MPI_COMM_WORLD,&status);
            printf(" mesg from %d of %d on %s\n",source,size,name);
        }
    }   
    MPI_Finalize();
    return 0;
}
Компилируем и запускаем на выполнение теми же командами, что и первый пример.
Оба примера компилировались и тестировались на компьютере с Debian Wheezy:
#uname -a
Linux myhost 3.2.0-4-686-pae #1 SMP Debian 3.2.39-2 i686 GNU/Linux

Комментариев нет: