Для ясности, MPI - это структурированная коммуникационная библиотека, а не какое-то эзотерическое расширение c для языка параллельного программирования. Это просто облегчает структурированный обмен данными между сущностями, называемыми ranks . Обычно ранги - это процессы, выполняющиеся на одном и том же компьютере или на отдельных компьютерах, связанных с какой-либо сетью, но это могут быть и другие виды взаимодействующих объектов. Важно то, что каждый ранг сам по себе важен, когда речь заходит о выполнении кода, и ему все равно, где находятся другие ранги в программе. Более того, все равно, работают ли другие ряды в одной программе. Фактически, хотя для MPI характерно, чтобы все ранги выполняли один и тот же код, так называемый SPMD или S ingle P rogram M ulitple D ata, вы можете написать отдельную программу для группы рангов или даже для каждого ранга, которая называется MPMD или M ultiple P rograms M ultiple D ata. MPI даже облегчает классический режим клиент-сервер и позволяет соединять отдельные задания MPI. SPMD проще программировать, так как вам нужно написать только одну программу.
Думайте о MPI просто как о посреднике (промежуточном программном обеспечении) между вашим кодом и системными API-интерфейсами c, которые обеспечивают простое взаимодействие между процессами и абстрагируется от таких вещей, как поиск фактических конечных точек других партнеров по связи (например, определение сетевых адресов и номеров портов, когда связь осуществляется по TCP / IP). Когда вы пишете браузер, который связывается по сети с веб-сервером, вам все равно, какой код выполняет сервер. И наоборот, серверу не важно, какой код выполняет ваш браузер. Пока оба говорят по одному протоколу, связь работает. То же самое относится и к MPI - если два ранга используют одну и ту же библиотеку MPI, они могут обмениваться данными.
Для успешного обмена данными в MPI необходимы только две вещи (в типичном двухточечном режиме). обмен данными):
- отправитель: ранг A готов отправить данные на ранг B и поэтому вызывает
MPI_Send(..., B, tag, MPI_COMM_SOMETHING);
- получатель: ранг B желает получать данные из ранга A и поэтому вызывает
MPI_Recv(..., A, tag, MPI_COMM_SOMETHING, ...);
Пока оба ранга указывают один и тот же тег и коммуникатор, а адреса в обоих вызовах отправки и получения совпадают попарно (включая способность получателя указывать подстановочные знаки источника и тега), обмен будет происходить независимо от того, где находятся фактические строки кода.
Ниже приведен совершенно правильный пример MPI:
rank_0. c
#include <stdio.h>
#include <mpi.h>
int main(void)
{
MPI_Init(NULL, NULL);
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int a;
MPI_Recv(&a, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("Rank %d got %d from rank 1\n", rank, a);
MPI_Finalize();
return 0;
}
rank_1. c
#include <mpi.h>
#include <stdio.h>
int main(int argc, char **argv)
{
MPI_Init(&argc, &argv);
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int a = 42;
MPI_Send(&a, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
printf("Rank %d sent %d to rank 0\n", rank, a);
MPI_Finalize();
return 0;
}
Скомпилируйте и запустите:
$ mpicc -o rank_0 rank_0.c
$ mpicc -o rank_1 rank_1.c
$ mpiexec -n 1 ./rank_0 : -n 1 ./rank_1
Rank 0 got 42 from rank 1
Rank 1 sent 42 to rank 0
Как видите, это две совершенно разные программы и они все еще счастливо работают вместе в одном задании MPI и могут обмениваться сообщениями.