Может показаться, что другим вариантом могло бы стать хранение a, b, n в структуре с тремя членами - два числа с плавающей точкой и целое - и попытка использовать аргумент datatype в функции MPI_Bcast(). Трудность здесь состоит в том, что тип datatype является одним из MPI_Datatype(), которые не являются пользовательскими типами, как структуры в C. Если определить тип:
float a;
float b;
int n;
} INDATA_TYPE
MPI обеспечивает частичное решение этой проблемы, разрешая пользователю во время выполнения создавать собственные типы данных MPI. Чтобы построить тип данных для MPI, необходимо определить расположение данных в типе: тип элементов и их относительные местоположения в памяти. Такой тип называют производным типом данных. Ниже приведена функция, которая будет строить производный тип, соответствующий INDATA_TYPE:
MPI-Datatype* message_type_ptr)
{
int block_lengths[3];
MPI_Aint displacements[3];
MPI_Aint addresses[4];
MPI_Datatype typelist[3];
/* Создает производный тип данных, содержащий
* два элемента float и один int */
/* Сначала нужно определить типы элементов */
typelist[0] = MPI_FLOAT;
typelist[1] = MPI_FLOAT;
typelist[2] = MPI_INT;
/* Определить количество элементов каждого типа */
block_lengths[0] = block_lengths[1] =
block_lengths[2] = 1;
/* Вычислить смещения элементов
* относительно indata */
MPI_Address(indata, &addresses[0]);
MPI_Address(&(indata->a), &addresses[1]);
MPI_Address(&(indata->b), &addresses[2]);
MPI_Address(&(indata->n), &addresses[3]);
displacements[0] = addresses[1] - addresses[0];
displacements[1] = addresses[2] - addresses[0];
displacements[2] = addresses[3] - addresses[0];
/* Создать производный тип */
MPI_Type_struct(3, block_lengths, displacements,
typelist, Message_type_ptr);
/* Зарегистрировать его для использования */
MPI_Type_commit(message_type_ptr);
} /* Build_derived_type */
Новый тип данных MPI можно использовать в любых коммуникационных функциях MPI. Чтобы использовать его, необходимо применять стартовый адрес переменной типа INDATA_TYPE в качестве первого аргумента, а производный тип данных - в качестве аргумента datatype. При этом функция Get_data() в примере принимает вид.
MPI_Datatype message_type; /* Аргументы для */
int root = 0; /* MPI_Bcast */
int count = 1;
if (my_rank == 0) {
printf(''Введите a, b, and n\n'');
scanf(''%f %f %d'', &(indata->a),
&(indata->b), &(indata->n));
}
Build_derived_type(indata, &message_type);
MPI_Bcast(indata, count, message_type, root,
MPI_COMM_WORLD);
} /* Get_data3 */
Производные типы данных строятся с помощью функции
MPI_Type_struct().
Синтаксис этой функции таков:
int* array_of_block_lengths,
MPI_Aint* array_of_displacements,
MPI_Datatype* array_of_types,
MPI_Datatype* newtype)
Следует также отметить, что newtype и элементы массива
array_of_types
все имеют тип MPI_Datatype. Поэтому функцию
MPI_Type_struct()
можно вызывать рекурсивно для построения более сложных производных
типов данных.