Совет пользователям: Этот пример показывает, как написать коллективную операцию обмена, которая использует кэширование для повышения эффективности после первого вызова. Стиль кодирования предполагает, что в результатах функции MPI возвращаются только ошибочные статусы.[]
/* ключ для этого модуля: */
static int gop_key = MPI_KEYVAL_INVALID;
typedef struct
{
int ref_count; /* счетчик ссылок */
/* другие обьявления, если они понадобятся */
} gop_stuff_type;
Efficient_Collective_Op (comm, ...)
MPI_Comm comm;
{
gop_stuff_type *gop_stuff;
MPI_Group group;
int foundflag;
MPI_Comm_group(comm, &group);
if (gop_key == MPI_KEYVAL_INVALID) /* Получение ключа на первом
вызове */
{
if (! MPI_Keyval_create(gop_stuff_copier,
gop_stuff_destructor,
&gop_key, (void *)0));
/* Получение ключа при назначении его копии, и исключение
действия обратного вызова. */
MPI_Abort (comm, 99);
}
MPI_Attr_get (comm, gop_key, &gop_stuff, &foundflag);
if (foundflag)
/* Этот модуль уже выполнился в этой группе.
Далее будет использоватся кэшируемая информация */
}
else
{/* Эта группа еще не была кэширована.
Это будет сделано сейчас. */
/* Во-первых, следует выделить память для нужных данных
и инициализировать cчетчик ссылки */
gop_stuff = gop_stuff_type *) malloc (sizeof(gop_stuff_type));
if (gop_stuff == NULL) { /* прерывается по ошибке нехватки
памяти */}
gop_stuff -> ref_count = 1;
/* Во вторых, следует заполнить *gop_stuff желаемым значени
ем.Эта часть здесь не показана */
/* Третье, следует сохранить gop_stuff как значение атрибута
*/
MPI_Attr_put (comm, gop_key, gop_stuff);
}
/* Затем, в любом случае, следует использовать значение
*gop_stuff, чтобы выполнить глобальную op ... */
}
/* Следующая подпрограмма вызывается MPI, когда группа удаляется
*/
gop_stuff_destructor (comm, keyval, gop_stuff, extra)
MPI_Comm comm;
int keyval;
gop_stuff_type *gop_stuff;
void *extra;
{
if (keyval != gop_key) { /* Прекращение работы из-за ошибки
программы*/ }
/* Освобождаемая группа удаляет одну ссылку на gop_stuff */
gop_stuff -> ref_count -= 1;
/* Если не осталось ни одной ссылки, то освобождаетcя память*/
if (gop_stuff -> ref_count == 0) {
free((void *)gop_stuff);
}
}
/* Следующая подпрограмма вызывается MPI, когда группа скопирована
*/
gop_stuff_copier (comm, keyval, extra, gop_stuff_in,
gop_stuff_out, flag)
MPI_Comm comm;
int keyval;
gop_stuff_type *gop_stuff_in, *gop_stuff_out;
void *extra;
{
if (keyval != gop_key) { /* Прекращение работы из-за ошибки
программы*/ }
/* Новая группа добавляет одну ссылку к gop_stuff */
gop_stuff -> ref_count += 1;
gop_stuff_out = gop_stuff_in;
}