Программирование для многопроцессорных систем в стандарте MPI - Шпаковский Г.И., Серикова Н.В.. Программирование для многопроцессорных систем в стандарте MPI -. Организация вычислений в многопроцессорных системах
Скачать 1.61 Mb.
|
Глава 6. ТОПОЛОГИИ ПРОЦЕССОВ 6.1. ВИРТУАЛЬНАЯ ТОПОЛОГИЯ Топология является необязательным атрибутом, который дополня- ет систему интра-коммуникаторов и не применяется в интер- коммуникаторах. Топология обеспечивает удобный способ обозначе- ния процессов в группе (внутри коммуникатора) и оказывает помощь исполнительной системе при размещении процессов в аппаратной среде. Во многих параллельных приложениях линейное распределе- ние номеров не отражает в полной мере логической структуры обме- нов между процессами, которая зависит от структуры задачи и ее ма- тематического алгоритма. Часто процессы описываются в двух- и трехмерных топологических средах. Наиболее общим видом тополо- гии является организация процессов, описываемая графовой структу- рой. В этой главе логическая организации процессов будет имено- ваться как “ виртуальная топология ”. Следует различать виртуальную топологию процессов и физиче- скую топологию процессов. Виртуальная топология должна приме- няться для назначения процессов физическим процессорам, если это позволит увеличить производительность обменов на данной машине. С другой стороны, описание виртуальной топологии зависит от кон- кретного приложения и является машинно-независимой. 159 Кроме возможности получить выгоду в производительности, вир- туальная топология может быть использована как средство обозначе- ния процессов, которое значительно улучшает читаемость программ. Взаимосвязь процессов может быть представлена графом. Узлы такого графа представляют процессы, ребра соответствуют связям между процессами. Стандарт MPI предусматривает передачу сообще- ний между любой парой процессов в группе. Не обязательно указы- вать канал связи явно. Следовательно, отсутствие канала связи в граф- схеме процессов не запрещает соответствующим процессам обмени- ваться сообщениями. Из этого следует, что такая связь в виртуальной топологии может отсутствовать, например, из-за того, что топология не представляет удобного способа обозначения этого канала обмена. Возможным следствием такого отсутствия может быть то, что автома- тическая программа для размещения процессов по процессорам (если такая будет существовать) не будет учитывать эту связь, и уменьшит- ся эффективность вычислений. Ребра в графе не взвешены, поэтому процесс может изображаться только подключенным или неподклю- ченным. Графовое представление топологии пригодно для всех приложе- ний. Однако во многих приложениях графовая структура является ре- гулярной и довольно простой, поэтому использование всех деталей графового представления будет неудобным и малоэффективным в ис- пользовании. Большая доля всех параллельных приложений использу- ет топологию колец, двумерных массивов или массивов большей раз- мерности. Эти структуры полностью определяются числом размерно- стей и количеством процессов для каждой координаты. Кроме того, отображение решеток и торов на аппаратуру обычно более простая задача, чем отображение сложных графов. Координаты в декартовой системе нумеруются от 0. Например, соотношение между номером процесса в группе и координатами в решетке (2 × 2) для четырех процессов будет следующим: coord (0,0): rank 0 сoord (0,1): rank 1 сoord (1,0): rank 2 сoord (1,1): rank 3 Функции MPI_GRAPH_CREATE и MPI_CART_CREATE ис- пользуются для создания универсальной (графовой) и декартовой то- пологий соответственно. Эти функции являются коллективными. Как 160 и для других коллективных обращений, программа для работы с топо- логией должна быть написана корректно, вне зависимости от того, яв- ляются ли обращения синхронизированными или нет. Функции создания топологии используют в качестве входа суще- ствующий коммуникатор comm_old , который определяет множество процессов, для которых и создается топология. Функция MPI_CART_CREATE может использоваться для описа- ния декартовой системы произвольной размерности. Для каждой ко- ординаты она определяет, является ли структура процессов периоди- ческой или нет. Таким образом, никакой специальной поддержки для структур типа гиперкуб не нужно. Локальная вспомогательная функ- ция MPI_DIMS_CREATE используется для вычисления сбалансиро- ванности процессов для заданного количества размерностей. Функция MPI_TOPO_TEST может использоваться для запроса о топологии, связанной с коммуникатором. Информация о топологии может быть извлечена из коммуникаторов с помощью функций MPI_GRAPHDIMS_GET и MPI_GRAPH_GET для графов и MPI_CARTDIM_GET и MPI_CART_GET – для декартовой топо- логии. Дополнительные функции обеспечивают работу с декартовой топологией: MPI_CART_RANK и MPI_CART_COORDS переводят декартовы координаты в номер группы и обратно; функция MPI_CART_SUB может использоваться для выделения декартова подпространства (аналогично функции MPI_COMM_SPLIT ). Функ- ция MPI_CART_SHIFT обеспечивает необходимую информацию для обмена между соседними процессами в декартовой системе коор- динат. Две функции MPI_GRAPH_NEIGHBORS_COUNT и MPI_GRAPH_NEIGHBORS используются для выделения соседних процессов на топологической схеме. Функция MPI_CART_SUB явля- ется коллективной для группы входного коммуникатора, остальные функции локальные. 6.2. ТОПОЛОГИЧЕСКИЕ КОНСТРУКТОРЫ 6.2.1. Конструктор декартовой топологии Функция MPI_CART_CREATE создает новый коммуникатор, к которому подключается топологическая информация. Если reorder = false , то номер каждого процесса в новой группе идентичен номеру в старой группе. Иначе функция может переупоря- дочивать процессы (возможно, чтобы обеспечить хорошее наложение 161 виртуальной топологии на физическую систему). Если полная размер- ность декартовой решетки меньше, чем размер группы коммуникато- ров, то некоторые процессы возвращаются с результатом MPI_COMM_NULL по аналогии с MPI_COMM_SPLIT. Вызов бу- дет неверным, если он задает решетку большего размера, чем размер группы. MPI_CART_CREATE(comm_old, ndims, dims, periods, reorder, comm_cart) IN comm_old исходный коммуникатор (дескриптор) IN ndims размерность создаваемой декартовой решетки (целое) IN dims целочисленный массив размера ndims, хранящий количест- во процессов по каждой координате IN periods массив логических элементов размера ndims, определяю- щий, периодична (true) или нет (false) решетка в каждой размерности IN reorder нумерация может быть сохранена (false) или переупорядо- чена (true) (логическое значение) OUT comm_cart коммуникатор новой декартовой топологии (дескриптор) int MPI_Cart_create(MPI_Comm comm_old, int ndims, int *dims, int *periods, int reorder, MPI_Comm *comm_cart) MPI_CART_CREATE(COMM_OLD, NDIMS, DIMS, PERIODS, REORDER, COMM_CART, IERROR) INTEGER COMM_OLD, NDIMS, DIMS(*), COMM_CART, IERROR LOGICAL PERIODS(*), REORDER MPI::Cartcomm MPI::Intracomm::Create_cart(int ndims, const int dims[], const bool periods[], bool reorder) const 6.2.2. Декартова функция MPI_DIMS_CREATE В декартовой топологии функция MPI_DIMS_CREATE помогает пользователю выбрать выгодное распределение процессов по каждой координате в зависимости от числа процессов в группе и некоторых ограничений, определенных пользователем. Эта функция использует- ся, чтобы распределить все процессы группы в n -мерную топологи- ческую среду (размер группы MPI_COMM_WORLD ). MPI_DIMS_CREATE(nnodes, ndims, dims) IN nnodes количество узлов решетки (целое) IN ndims число размерностей декартовой решетки(целое) INOUT dims целочисленный массив размера ndims, указывающий коли- чество вершин в каждой размерности. 162 int MPI_Dims_create(int nnodes, int ndims, int *dims) MPI_DIMS_CREATE(NNODES, NDIMS, DIMS, IERROR) INTEGER NNODES, NDIMS, DIMS(*), IERROR void MPI::Compute_dims(int nnodes, int ndims, int dims[]) Элементы массива dims описывают декартову решетку координат с числом размерностей ndims и общим количеством узлов nnodes Количество узлов по размерностям нужно сделать, насколько воз- можно, близкими друг другу, используя соответствующий алгоритм делимости. Вызывающая подпрограмма может дальше ограничить выполнение этой функции, задавая количество элементов массива dims Если размерность dims[i] есть положительное число, функция не будет изменять число узлов в направлении i ; будут изменены только те элементы, для которых dims[i] = 0 .Отрицательные значения dims[i] неверны. Также будет неверно, если значение nnodes не крат- но произведению dims[i] . Аргумент dims[i] , установленный вызы- вающей программой, будет упорядочен по убыванию. Массив dims удобен для использования в функции MPI_CART_CREATE в каче- стве входного. Функция является локальной. Пример 6.1 dims перед вызовом вызов функции dims после возврата управления (0,0) MPI_DIMS_CREATE(6, 2, dims) (3,2) (0,0) MPI_DIMS_CREATE(7, 2, dims) (7,1) (0,3,0) MPI_DIMS_CREATE(6, 3, dims) (2,3,1) (0,3,0) MPI_DIMS_CREATE(7, 3, dims) Ошибка 6.2.3. Конструктор универсальной (графовой) топологии Функция MPI_GRAPH_CREATE передает дескриптор новому коммуникатору, к которому присоединяется информация о графовой топологии. Если reorder = false , то номер каждого процесса в новой группе идентичен его номеру в старой группе. В противном случае функция может переупорядочивать процессы. Если количество узлов графа nnodes меньше, чем размер группы коммуникатора, то некото- рые процессы возвращают значение MPI_COMM_NULL по аналогии с MPI_CART_SPLIT и MPI_COMM_SPLIT. Вызов будет неверным, если он определяет граф большего размера, чем размер группы исход- ного коммуникатора. 163 MPI_GRAPH_CREATE(comm_old, nnodes, index, edges, reorder, comm_graph) IN comm_old входной коммуникатор (дескриптор) IN nnodes количество узлов графа (целое) IN index массив целочисленных значений, описывающий степени вершин IN edges массив целочисленных значений, описывающий ребра графа IN reorder номера могут быть переупорядочены ( true) или нет ( false) OUT comm_graph построенный коммуникатор с графовой топологией (дескриптор) int MPI_Graph_create(MPI_Comm comm_old, int nnodes, int *index, int *edges, int reorder, MPI_Comm *comm_graph) MPI_GRAPH_CREATE(COMM_OLD, NNODES, INDEX, EDGES, REORDER, COMM_GRAPH, IERROR) INTEGER COMM_OLD, NNODES, INDEX(*), EDGES(*), COMM_GRAPH, IERROR LOGICAL REORDER int MPI::Cartcomm::Get_dim() const. Структуру графа определяют три параметра: nnodes, index и edges Nnodes – число узлов графа от 0 до nnodes-1. i- ый элемент массива index хранит общее число соседей первых i вершин графа. Списки соседей вершин 0, 1, ..., nnodes-1 хранятся в последовательно- сти ячеек массива edges . Общее число элементов в index есть nnodes , а общее число элементов в edges равно числу ребер графа. 6.2.4. Топологические функции запроса Если топология была определена одной из вышеупомянутых функций, то информация об этой топологии может быть получена с помощью функций запроса. Все они являются локальными вызовами. MPI_TOPO_TEST(comm, status) IN comm коммуникатор (дескриптор) OUT status тип топологии коммуникатора comm (альтернатива) int MPI_Topo_test(MPI_Comm comm, int *status) MPI_TOPO_TEST(COMM, STATUS, IERROR) INTEGER COMM, STATUS, IERROR int MPI::Comm::Get_topology() const Функция MPI_TOPO_TEST возвращает тип топологии, передан- ной коммуникатору. 164 Выходное значение status имеет одно из следующих значений: MPI_GRAPH топология графа MPI_CART декартова топология MPI_UNDEFINED топология не определена Функции MPI_GRAPHDIMS_GET и MPI_GRAPH_GET воз- вращают графо-топологическую информацию, которая была связана с коммуникатором с помощью функции MPI_GRAPH_CREATE MPI_GRAPHDIMS_GET(comm, nnodes, nedges) IN comm коммуникатор группы с графовой топологией (дескриптор) OUT nnodes число вершин графа (целое, равно числу процессов в группе) OUT nedges число ребер графа (целое) int MPI_Graphdims_get(MPI_Comm comm, int *nnodes, int *nedges) MPI_GRAPHDIMS_GET(COMM, NNODES, NEDGES, IERROR) INTEGER COMM, NNODES, NEDGES, IERROR void MPI::Graphcomm::Get_dims(int nnodes[], int nedges[]) const Информация, представляемая MPI_GRAPHDIMS_GET, может быть использована для корректного определения размера векторов index и edges для последующего вызова функции MPI_GRAPH_GET MPI_GRAPH_GET(comm, maxindex, maxedges, index, edges) IN comm коммуникатор с графовой топологией (дескриптор) IN maxindex длина вектора index (целое) IN maxedges длина вектора edges (целое) OUT index целочисленный массив, содержащий структуру графа (под- робнее в описании функции MPI_GRAPH_CREATE) OUT edges целочисленный массив, содержащий структуру графа int MPI_Graph_get(MPI_Comm comm, int maxindex, int maxedges, int *index, int *edges) MPI_GRAPH_GET(COMM, MAXINDEX, MAXEDGES, INDEX, EDGES, IERROR) INTEGER COMM, MAXINDEX, MAXEDGES, INDEX(*), EDGES(*), IERROR void MPI::Graphcomm::Get_topo (int maxindex, int maxedges, int index[], int edges[]) const Функции MPI_CARTDIM_GET и MPI_CART_GET возвращают информацию о декартовой топологии, которая была связана с функ- цией MPI_CART_CREATE 165 MPI_CARTDIM_GET(comm, ndims) IN comm коммуникатор с декартовой топологией (дескриптор) OUT ndims число размерностей в декартовой топологии системы (целое) int MPI_Cartdim_get(MPI_Comm comm, int *ndims) MPI_CARTDIM_GET(COMM, NDIMS, IERROR) INTEGER COMM, NDIMS, IERROR int MPI::Cartcomm::Get_dim() const MPI_CART_GET(comm, maxdims, dims, periods, coords) IN comm коммуникатор с декартовой топологией (дескриптор) IN maxdims длина векторов dims, periods и coords (целое) OUT dims число процессов по каждой декартовой размерности (це- лочисленный массив) OUT periods периодичность ( true/ false) для каждой декартовой раз- мерности (массив логических элементов) OUT coords координаты вызываемых процессов в декартовой системе координат (целочисленный массив) int MPI_Cart_get(MPI_Comm comm, int maxdims, int *dims, int *periods, int *coords) MPI_CART_GET(COMM, MAXDIMS, DIMS, PERIODS, COORDS, IERROR) INTEGER COMM, MAXDIMS, DIMS(*), COORDS(*), IERROR LOGICAL PERIODS(*) Void MPI::Cartcomm::Get_topo(int maxdims, int dims[], bool periods[], int coords[]) const Для группы процессов с декартовой структурой функция MPI_CART_RANK переводит логические координаты процессов в номера, которые используются в процедурах парного обмена. MPI_CART_RANK(comm, coords, rank) IN comm коммуникатор с декартовой топологией (дескриптор) IN coords целочисленный массив (размера ndims), описывающий декарто- вы координаты процесса OUT rank номер указанного процесса (целое) int MPI_Cart_rank(MPI_Comm comm, int *coords, int *rank) MPI_CART_RANK(COMM, COORDS, RANK, IERROR) INTEGER COMM, COORDS(*), RANK, IERROR 166 Int MPI::Cartcomm::Get_cart_rank(const int coords[]) const. Для размерности i с periods(i) = true , если координата cords(i) вы- ходит за границу диапазона – coords(i)<0 или coords(i)≥dims(i) , она автоматически сдвигается назад к интервалу 0≤coords(i) . Вы- ход координат за пределы диапазона неверен для непериодических размерностей. Функция MPI_CART_COORDS используется для перевода номе- ра в координату. MPI_CART_COORDS(comm, rank, maxdims, coords) IN comm коммуникатор с декартовой топологией (дескриптор) N rank номер процесса внутри группы comm (целое) IN maxdims длина вектора coord (целое) OUT coords целочисленный массив (размера ndims), содержащий декар- товы координаты указанного процесса (целое) int MPI_Cart_coords(MPI_Comm comm, int rank, int maxdims, int *coords) MPI_CART_COORDS(COMM, RANK, MAXDIMS, COORDS, IERROR) INTEGER COMM, RANK, MAXDIMS, COORDS(*), IERROR Void MPI::Cartcomm_Get_coords (int rank, int maxdims, int coords[] ) const MPI_GRAPH_NEIGHBORS_COUNT и MPI_GRAPH_NEIGHBORS предоставляют похожую информацию для графической топологии. MPI_GRAPH_NEIGHBORS_COUNT(comm, rank, nneighbors) IN comm коммуникатор с графовой топологией (дескриптор) IN rank номер процесса в группе comm (целое) OUT nneighbors номера процессов, являющихся соседними указанному процессу (целочисленный массив) int MPI_Graph_neighbors_count(MPI_Comm comm, int rank, int *nneighbors) MPI_GRAPH_NEIGHBORS_COUNT(COMM, RANK, NNEIGHBORS, IERROR) INTEGER COMM, RANK, NNEIGHBORS, IERROR int MPI::Graphcomm::Get_neighbors_count (int rank) const MPI_GRAPH_NEIGHBORS(comm, rank, maxneighbors, neighbors) IN comm коммуникатор с графовой топологией (дескриптор) IN rank номер процесса в группе comm (целое) IN maxneighbors размер массива neighbors (целое) OUT neighbors номера процессов, соседних данному (целочисленный массив) int MPI_Graph_neighbors(MPI_Comm comm, int rank, int maxneighbors, int *neighbors) 167 MPI_GRAPH_NEIGHBORS(COMM, RANK, MAXNEIGHBORS, NEIGHBORS, IERROR) INTEGER COMM, RANK, MAXNEIGHBORS, NEIGHBORS(*), IERROR void MPI::Graphcomm::Get_neighbors (int rank, int maxneighbors, int neighbors[] ) const Пример 6.2. Предположим, что comm является коммуникатором с топологией типа “тасовка”. Пусть группа содержит 2 n процессов. Каждый процесс задан дво- ичным n – разрядным кодом а 1 , а 2 , …, а n , где а i ∈ {0,1} и имеет трех соседей: exchange (а 1 , …, а n ) = а 1 , …, а n-1 , â n (â = 1-а); shuffle (а 1 , …, а n ) = а 2 , …, а n , а 1 ; unshuffle(а 1 , …, а n ) = а n , а 1 , …, а n-1. Таблица связей каждого процесса с соседями для n=3 узлы exchange соседи(1) shuffle соседи(2) unshuffle соседи(3) 0 (000) 1 0 0 1 (001) 0 2 4 2 (010) 3 4 1 3 (011) 2 6 5 4 (100) 5 1 2 5 (101) 4 3 6 6 (110) 7 5 3 7 (111) 6 7 7 Предположим, что коммуникатор comm имеет эту топологию. Представленный ниже фрагмент программы в цикле обходит трех со- седей и делает соответствующую перестановку для каждого. ! пусть каждый процесс хранит действительное число А ! получение информации о соседях CALL MPI_COMM_RANK(comm, myrank, ierr) CALL MPI_GRAPH_NEIGHBORS(comm, myrank, 3, neighbors, ierr) ! выполнение перестановки для exchange CALL MPI_SENDRECV_REPLACE(A, 1, MPI_REAL, neighbors(1), 0, neighbors(1), 0, comm, status, ierr) ! выполнение перестановки для shuffle CALL MPI_SENDRECV_REPLACE(A, 1, MPI_REAL, neighbors(2), 0, neighbors(3), 0, comm, status, ierr) ! выполнение перестановки для unshuffle 168 CALL MPI_SENDRECV_REPLACE(A, 1, MPI_REAL, neighbors(3), 0, neighbors(2), 0, comm, status, ierr) 6.2.5. Сдвиг в декартовых координатах Если используется декартова топология, то операцию MPI_SENDRECV можно выполнить путем сдвига данных вдоль на- правления координаты. В качестве входного параметра MPI_SENDRECV использует номер процесса-отправителя для прие- ма и номер процесса-получателя – для передачи. Если функция MPI_CART_SHIFT выполняется для декартовой группы процессов, то она передает вызывающему процессу эти номера, которые затем могут быть использованы для MPI_SENDRECV . Пользователь опре- деляет направление координаты и величину шага (положительный или отрицательный). Эта функция является локальной. MPI_CART_SHIFT(comm, direction, disp, rank_source, rank_dest) IN comm коммуникатор с декартовой топологией (дескриптор) IN direction координата сдвига ( целое) IN disp направление смещения (> 0: смещение вверх, < 0: смещение вниз) ( целое) OUT rank_source номер процесса-отправителя (целое) OUT rank_dest номер процесса-получателя (целое) int MPI_Cart_shift(MPI_Comm comm, int direction, int disp, int *rank_source, int *rank_dest) MPI_CART_SHIFT(COMM, DIRECTION, DISP, RANK_SOURCE, RANK_DEST, IERROR) INTEGER COMM, DIRECTION, DISP, RANK_SOURCE, RANK_DEST, IERROR Void MPI::Cartcomm::Shift(int direction, int disp, int& rank_source, int& rank_dest) const Аргумент direction указывает размерность (координату) по кото- рой сдвигаются данные. Координаты маркируются от 0 до ndims-1 , где ndims – число размерностей. В зависимости от периодичности де- картовой группы в указанном направлении координаты MPI_CART_SHIFT указывает признаки для кольцевого сдвига или для сдвига без переноса. В случае сдвига без переноса в rank_source или rank_dest может быть возвращено значение MPI_PROC_NULL для указания, что процесс-отправитель или процесс-получатель при сдвиге вышли из диапазона. 169 Пример 6.3. Коммуникатор comm имеет двумерную периодическую декартову топологию. Двумерная матрица элементов типа REAL хра- нит один элемент на процесс в переменной A . Нужно выполнить ско- шенное преобразование матрицы путем сдвига столбца i (вертикаль- но, то есть вдоль столбца) i раз. ! определяется номер процесса CALL MPI_COMM_RANK(comm, rank, ierr) ! определяются декартовы координаты CALL MPI_CART_COORDS(comm, rank, maxdims, coords, ierr) ! вычисляются номера процесса-отправителя и процесса-получателя при сдвиге CALL MPI_CART_SHIFT(comm, 0, coords(2), source, dest, ierr) ! «скошенный» массив CALL MPI_SENDRECV_REPLACE(A, 1, MPI_REAL, dest, 0, source, 0, comm, status, ierr) 6.2.6. Декомпозиция декартовых структур MPI_CART_SUB(comm, remain_dims, newcomm) IN comm коммуникатор с декартовой топологией (дескриптор) IN remain_dims i-й элемент в remain_dims показывает, содержится ли i-я размерность в подрешетке (true) или нет (false) (вектор ло- гических элементов) OUT newcomm коммуникатор, содержащий подрешетку, которая включает вызываемый процесс (дескриптор) int MPI_Cart_sub(MPI_Comm comm, int *remain_dims, MPI_Comm *newcomm) MPI_CART_SUB(COMM, REMAIN_DIMS, NEWCOMM, IERROR) INTEGER COMM, NEWCOMM, IERROR LOGICAL REMAIN_DIMS(*) MPI::Cartcomm MPI::Cartcomm::Sub(const bool remain_dims[]) comst Если декартова топология была создана с помощью функции MPI_CART_CREATE , то функция MPI_CART_SUB может исполь- зоваться для декомпозиции группы в подгруппы, которые являются декартовыми подрешетками, и построения для каждой подгруппы коммуникаторов с подрешеткой с декартовой топологией. Пример 6.4 Допустим, что MPI_CART_CREATE создала решетку размером (2 × 3 × 4). Пусть remain_dims = (true, false, true ). Тогда обращение к MPI_CART_SUB (comm, remain_dims, comm_new) создаст три ком- муникатора, каждый с восьмью процессами размерности 2×4 в декар- 170 товой топологии. Если remain_dims = (false, false, true ), то обращение к функции MPI_CART_SUB (comm, remain_dims, comm_new) соз- дает шесть непересекающихся коммуникаторов, каждый с четырьмя процессами в одномерной декартовой топологии. Пример 6.5 Дифференциальные уравнения в частных производных, например уравнение Пуассона, могут быть решены на прямоугольной решетке. Пусть процессы располагаются в двумерной структуре. Каждый про- цесс запрашивает номера соседей в четырех направлениях (вверх, вниз, вправо, влево). Числовая задача решается итерационным мето- дом, детали которого скрыты в подпрограмме. На каждой итерации каждый процесс вычисляет новые значения для функции в области решетки, за которую он ответственен. Затем процесс на своих грани- цах должен обменяться значениями функции с соседними процессами. Например, подпрограмма обмена может содержать вызов функции MPI_SEND (..., neigh_rank (1), ...) , чтобы затем послать модифициро- ванные значения функции левому соседу (i-1, j). integer ndims, num_neihg logical reorder parameter (ndims=2,num_neigh=4,reorder=.true.) integer comm, comm_cart, dims (ndims), neigh_def (ndims), ierr integer neigh_rank (num_neigh), own_position (ndims), i,j logical periods (ndims) real*8 u(0:101,0:101), f(0:101,0:101) data dims /ndims*0/ comm = MPI_COMM_WORLD ! устанавливает размер решетки и периодичность call MPI_DIMS_CREATE (comm, ndims, dims, ierr) periods (1) = .TRUE. periods (2) = .TRUE. ! создает структуру в группе WORLD и запрашивает собственную позицию call MPI_CART_CREATE (comm, ndims, dims, periods, reorder, comm_cart, ierr) call MPI_CART_GET (comm_cart, ndims, dims, periods, own_position, ierr) ! просматривает номера соседей, собственные координаты есть (i,j). ! cоседи – процессы с номерами (i-1,j), (i+1,j), (i,j-1), (i,j+1) i = own_position(1) j = own_position(2) neigh_def(1)= i-1 neigh_def(2)= j call MPI_CART_RANK (comm_cart, neigh_def, neigh_rank(1), ierr) 171 neigh_def(1)= i+1 neigh_def(2)= j call MPI_CART_RANK (comm_cart, neigh_def, neigh_rank(2), ierr) neigh_def(1)= i neigh_def(2)= j-1 call MPI_CART_RANK (comm_cart, neigh_def, neigh_rank(3), ierr) neigh_def(1)= i neigh_def(2)= j+1 call MPI_CART_RANK (comm_cart, neigh_def, neigh_rank(4), ierr) ! инициализация функций решеток и начало итерации call init (u,f) do 10 it=1,100 call relax (u,f) ! обмен данными с соседними процессами call exchange (u, comm_cart, neigh_rank, num_neigh) 10 continue call output (u) end КОНТРОЛЬНЫЕ ВОПРОСЫ К ГЛАВЕ 6 Контрольные вопросы к 6.1 1. Топология – это частный случай коммуникатора? 2. Топология применима к интра-коммуникаторам или интер-коммуникаторам? 3. В чем различие между виртуальной и физической топологией процессов? 4. Можно ли создать виртуальную топологию на основании любого коммуника- тора, полученного с помощью процедур из главы 5? 5. Приведите примеры задач, где использование декартовой топологии было бы очень удобным. Контрольные вопросы к 6.2 1. Функции создания виртуальной топологии коллективные или локальные? 2. Как создать декартову топологию размерности 1? 3. Что произойдет, если полная размерность декартовой решетки меньше, чем размер коммуникатора? А если больше? 4. Опишите математическую функцию, которая реализуется при вызове MPI_Dims_create. 5. Объясните, почему произойдет ошибка в четвертом случае примера 6.1. 6. Что возвращает функция MPI_Tоpo_test? 7. Необходимо ли вызывать функцию MPI_Graphdims_get перед вызовом функ- ции MPI_Graph_get? Почему? 8. Какую информацию о декартовой топологии возвращает функция MPI_Cartdim_get? А – MPI_Cart_get? 9. Пусть имеются четыре процесса 0, 1, 2, 3 со следующей матрицей смежности: 172 Процесс Соседи 0 1, 3 1 0 2 3 3 0, 2 Опишите параметры nnodes, index, edges при создании графовой топологии вызовом функции MPI_Graph_create (…, nnodes, *index, *edges, …) для данного случая. 10. Какие функции переводят логические координаты процесса с декартовой структурой, графовой топологией в номер, который используется в процеду- рах парного обмена? 11. Какие функции переводят номер, который используется в процедурах парного обмена в логические координаты процесса с декартовой структурой и графо- вой топологией? 12. Опишите создание коммуникатора comm в примере 6.2. 13. Как определить “соседей” по топологии? 14. Сколько всевозможных коммуникаторов можно получить при вызове функ- ции MPI_Cart_sub для одной декартовой топологии, созданной функцией MPI_Cart_create? Задания для самостоятельной работы 6.1. Напишите программу, которая рассылает данные от процесса ноль всем другим процессам по конвейеру. Этот означает, что процесс i должен принять данные от i-1 и послать их процессу i + 1, и так до тех пор, пока не будет достиг- нут последний процесс. Будем считать, что данные содержат единственное целое. Процесс ноль читает данные от пользователя, пока не появится на входе отрица- тельное целое число. Выполните задание, используя картезианскую топологию процессов размерности 1; для определения номеров соседнихпроцессов исполь- зуйте MPI_Cart_shift. 6.2. Выполните задание 6.1, используяMPI_Isend и MPI_Irecv, MPI_Wait. Для возможности совмещения вычислений и обмена введите процедуру для вычисле- ния произвольного характера. 6.3. Выполните задание 6.1, организовав передачу данных по кольцу, т.е. по- следний процесс должен передать данные нулевому, который их выводит на эк- ран. 6.4. Выполните задание 5.5 с использованием декартовой топологии. |