Ранее было указано, что существует возможность связать с коммуникатором
дополнительную информацию, которая находится вне группы и контекста.
Эта дополнительная информация кэширована с коммуникатором, и одной
из самых важных ее частей является топология. В MPI топология представляет
собой механизм для того, чтобы связать с процессами, принадлежащими
группе, различные схемы адресации. Топология MPI - виртуальная, т.
е. может не существовать никакого простого отношения между структурой
процессов, определенной виртуальной топологией и фактической физической
структурой параллельной машины.
Известны два основных типа виртуальной топологии, которая может
быть создана MPI, - декартова топология, или топология сетки, и топология
графа. Первый тип является подмножеством второго. Однако из-за активного
использования сеток в приложениях выделяется отдельное подмножество
функций MPI, цель которого - манипуляция виртуальными сетками.
В алгоритме Фокса необходимо идентифицировать процессы
MPI_COMM_WORLD
координатами квадратной сетки, причем каждая строка и колонка
сетки должны формировать свой собственный коммуникатор.
Сначала необходимо связать квадратную структуру сетки с
MPI_COMM_WORLD.
Чтобы сделать это, нужно определить следующую информацию:
Число измерений сетки (в данном случае 2).
Размер каждого измерения. В данном случае, это просто число строк
и число колонок( q строк и q колонок).
Периодичность каждого измерения. В данном случае эта информация определяет,
является ли первый элемент в каждой строке или колонке смежным с последним
элементом в этой строке или колонке соответственно. Так как алгоритм
требует "кругового" сдвига подматриц в каждой колонке,
нужно, чтобы второе измерение было периодическим. При этом неважно,
является ли периодическим первое измерение.
Наконец, MPI предлагает пользователю опцию, позволяющую системе оптимизировать
отображение сетки процессов на основные физические процессоры, возможно
переупорядочивая процессы в группе, принадлежащей коммуникатору. Поскольку
порядок процессов в MPI_COMM_WORLD не имеет значения, можно позволить
системе выполнить переупорядочение.
После этого нужно просто выполнить код:
MPI_Comm grid_comm;
int dimensions[2];
int wrap_around[2];
int reorder = 1;
dimensions[0] = dimensions[1] = q;
wrap_around[0] = wrap_around[1] = 1;
MPI_Cart_create(MPI_COMM_WORLD, 2, dimensions,
wrap_around, reorder, &grid_comm);
После выполнения кода коммуникатор grid_comm будет содержать
все процессы MPI_COMM_WORLD (возможно переупорядоченные)
и ассоциированную с ними двухмерную систему декартовых координат. Чтобы
процесс мог определить свои координаты, он должен вызвать функцию
MPI_Cart_coords():
int coordinates[2];
int my_grid_rank;
MPI_Comm_rank(grid_comm, &my_grid_rank);
MPI_Cart_coords(grid_comm, my_grid_rank, 2,
coordinates);
Следует отметить, что для получения ранга процесса в grid_comm
нужно вызвать MPI_Comm_rank(). Это необходимо потому, что
в вызове MPI_Cart_create() установлен флаг переупорядочения
и, следовательно, первоначальный ранг процесса в MPI_COMM_WORLD,
возможно, будет изменен в grid_comm.
Обратной функцией к MPI_Cart_coords() является
MPI_Cart_rank():
int MPI_Cart_rank(grid_comm, coordinates, &grid_rank)
Задавая координаты процесса, с помощью MPI_Cart_rank()
можно получить ранг этого процесса в process_rank.
Синтаксис MPI_Cart_create():
int MPI_Cart_create(MPI_Comm old_comm,
int number_of_dims, int* dim_sizes,
int* periods, int reorder, MPI_Comm* cart_comm)
MPI_Cart_create() создает новый коммуникатор cart_comm
путем кэширования декартовой топологии с old_comm. Информация
относительно структуры декартовой топологии содержится в параметрах
number_of_dims, dim_sizes,periods. Первый
параметр содержит число измерений в декартовой системе координат.
Следующие два являются массивами с размером, равным числу измерений.
Массив dim_sizes определяет порядок каждого измерения, а
periods определяет, является ли измерение циклическим или линейным.
Процессы в cart_comm ранжируются в порядке строк. При этом
первый ряд состоит из процессов 0, 1,..., dim_sizes[0]-1,
второй ряд - из процессов dim_sizes[0],dim_sizes[0]+1 , ... ,
2*dim_sizes[0]-1
и т.д. Таким образом, иногда выгодно изменить относительное ранжирование
процессов в old_comm. Например, пусть физическая топология
- это сетка 3x3,а процессы (номера) в old_comm назначены
на процессоры (квадраты сетки) следующим образом (рис. 5):
3
4
5
0
1
2
6
7
8
Рис. 5. Распределение процессов по процессорам
Поскольку MPI_Cart_create() создает новый коммуникатор,
она является коллективной операцией.
int MPI_Cart_rank(MPI_Comm comm, int* coordinates,
int* rank);
int MPI_Cart_coords(MPI_Comm comm, int rank,
int number_of_dims, int* coordinates)
MPI_Cart_rank() возвращает ранг процесса в декартовом коммуникаторе
comm, при этом процесс имеет координаты coordinates.
Координаты содержатся в массиве в порядке, эквивалентном порядку размерностей
декартовой топологии, ассоциированной с comm. MPI_Cart_coords()
возвращает координаты процесса с рангом rank в декартовом
коммуникаторе comm. Обе функции являются локальными.