RefNUMA – библиотека для организации виртуальной общей памяти в программах, использующих MPI.

А. О. Лацис

Пример 1. Инициализация, терминация, общее управление.

Ниже представлен текст программы, все процессы которой совместно формируют выходной файл output.dat. В этом файле каждый процесс должен напечатать собственный номер и общее число процессов. Выдачи от разных процессов должны идти в порядке номеров процессов, не перепутываясь. Возможности MPI в этой программе напрямую не используются.

#include <stdio.h>;
#include <stdlib.h>
#include <mpi.h>
#include <coarray.h>
#include <shared.h>
    COARRAY_MEM_ALLOC( 2000000000l );
    int main( int argc, char *argv[] )
{
    int i, my_node, n_nodes;
    FILE *fp;
/***/
    COARRAY_Init( &argc, &argv );
    my_node = coarray_my_node();
    n_nodes = coarray_n_nodes();
    if ( my_node == 0 )
     {
      fp = fopen( "output.dat", "w" );
      fclose( fp );
     }
    for ( i = 0; i < n_nodes; i++ )
     {
      coarray_barrier();
      if ( i == my_node )
       {
        fp = fopen( "output.dat", "a" );
        fprintf( fp, "Hello, I am %d of %d\n", my_node, n_nodes );
        fclose( fp );
       }
     }
    COARRAY_Finalize();
    return 0;
}

Заголовочные файлы coarray.h и shared.h должны включаться любой программой, использующей RefNUMA. Вызов макроса COARRAY_MEM_ALLOC() (этот макрос не выполняемый) обязателен. Он должен присутствовать в программе строго один раз, его рекомендуется располагать перед текстом функции main(). Аргумент этого макроса – целочисленная константа типа long – означает объем памяти в байтах, резервируемой программой для последующего использования библиотекой RefNUMA для своих внутренних нужд. Значение этого аргумента подбирается «на глазок», с запасом. В последующих примерах мы узнаем, как можно в конце работы программы спросить у RefNUMA, сколько зарезервированной таким образом памяти ей реально потребовалось.

Вызовы COARRAY_Init() и COARRAY_Finalize() аналогичны MPI_Init() и MPI_Finalize(), и заменяют их (если есть вызов COARRAY_Init(), то MPI_Init() вызывать не следует).

coarray_my_node() и coarray_n_nodes() служат для выяснения собственного номера процесса и общего числа процессов в параллельной программе, соответственно. Номер процесса равен номеру процесса MPI в коммуникаторе MPI_COMM_WORLD.

Единственным средством синхронизации процессов в RefNUMA является барьерная синхронизация, которая выполняется при обращении к coarray_barrier(). В данном примере синхронизация используется для того, чтобы процессы записали собственный номер и общее число процессов в файл строго в порядке собственных номеров, и выдачи от разных процессов при этом не перемешивались. Для достижения этой цели в данном тривиальном примере можно было бы воспользоваться и вызовом функции MPI_Barrier( MPI_COMM_WORLD ), но в общем случае, в реальных программах, следует использовать coarray_barrier(). В отличие от функции MPI_Barrier(), функция coarray_barrier() выполняет не только барьерную синхронизацию, но и еще некоторые очень важные действия, без которых общая память RefNUMA просто не сможет работать.

◄ Введение Пример 2 ►
 
 
 
 
 
 
 
 
  Тел. +7(499)220-79-72; E-mail: inform@kiam.ru