Параллельное программирование: Учебное пособие, страница 127

void *attribute, int *flag)

возвращает значение атрибута attribute, соответствующее значению ключа keyval. Первый параметр задает коммуникатор, с которым связан атрибут. Если ключа со значением keyval нет, возникает ошибка. Ошибки не возникает, если значение key существует, но соответствующий атрибут не присоединен к коммуникатору comm. В этом случае возвращается значение флага flag = false.

Вызов MPI_Attr_put передает в параметре attribute_val значение атрибута, а вызов подпрограммы MPI_Attr_get передает в параметре attribute_val адрес, по которому возвращается значение атрибута. Атрибуты должны извлекаться из программ, написанных на тех же языках, на которых они задавались с помощью вызова подпрограммы MPI_Attr_put.

Подпрограмма MPI_Attr_delete:

int MPI_Attr_delete(MPI_Comm comm, int keyval)

удаляет атрибут с указанным значением ключа. Делается это с помощью функции удаления атрибута delete_fn, заданной при создании keyval. Параметр comm задает коммуникатор, с которым связан атрибут. Все аргументы данной подпрограммы входные. При любом дублировании коммуникатора с помощью подпрограммы MPI_Comm_dup вызываются все функции копирования для атрибутов, установленных в данный момент времени. Делается это в произвольном порядке. Аналогичные действия выполняются при удалении коммуникатора вызовом MPI_Comm_free, но при этом вызываются все функции удаления.

Текст 6.6. Пример кэширования атрибутов

/* Кэшируется и отыскивается ранг процесса с коммуникатором */

#include <stdio.h>

#include "mpi.h"

#include <stdlib.h>

main(int argc, char* argv[])

{

    int p;

    int my_rank;

    MPI_Comm  io_comm;        /* Коммуникатор для I/O          */

    int       IO_KEY;         /* Ключ атрибута процесса I/O */

    int*      io_rank_ptr;    /* Атрибуты – указатели           */

void*     extra_arg;      /* Неиспользован                        */

    int       flag;

    int*      io_rank_attr;

    MPI_Init(&argc, &argv);

    MPI_Comm_size(MPI_COMM_WORLD, &p);

    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

/* Получаем отдельный коммуникатор для функций     */

/* ввода/вывода дублированием MPI_COMM_WORLD */

MPI_Comm_dup(MPI_COMM_WORLD, &io_comm);

/* Открываем ключ атрибута */

    MPI_Keyval_create(MPI_DUP_FN, MPI_NULL_DELETE_FN,

&IO_KEY, extra_arg);

/* Распределение памяти для содержимого атрибута */

io_rank_ptr = (int*) malloc(sizeof(int));

/* Установить содержимое атрибута */

    *io_rank_ptr = 0;

/* Связываем атрибут с коммуникатором io_comm */

MPI_Attr_put(io_comm, IO_KEY, io_rank_ptr);

/* Отыскиваем по ключу ранг процесса ввода/вывода */

MPI_Attr_get(io_comm, IO_KEY,

&io_rank_attr, &flag);

/* Если ни одного ранга с таким ключом не     */

/* найдено, то значение flag будет равно нулю */

    if ((flag != 0) && (my_rank == *io_rank_attr))

      {

        printf("Greetings from the I/O Process!\n");

        printf("My rank is %d\n", *io_rank_attr);

      }

    MPI_Finalize();

}  /* main */

6.8  Ввод и вывод

В состав NT-MPICH входит библиотека ROMIO, содержащая подпрограммы параллельного ввода/вывода и основные операции с файлами.

6.8.1  Основные операции с файлами

Открытие доступа к файлу для всех процессов из области взаимодействия, определяемой заданным коммуникатором, осуществляется с помощью подпрограммы MPI_File_open:

int MPI_File_open(MPI_Comm comm, char *filename,

   int amode, MPI_Info info, MPI_File *fh)

где:

·  comm — коммуникатор;

·  filename — имя файла;

·  amode — режим доступа к файлу (См. табл. 6.4);

·  info — информационный параметр;

·  fn— файловый дескриптор, который является выходным для этой подпрограммы.

Открытие файла является коллективной операцией, а коммуникатор обязательно должен быть интракоммуникатором, то есть доступ к файлу открывается, при прочих равных условиях, лишь для процессов, находящихся на одном процессоре Во всех обращениях должны использоваться одинаковые значения параметров amode и filename, а значение info может быть разным.