MPI C中自定义操作/数据类型实现结构体Allreduce以保留最大绝对值符号
解决方案
完全可以通过自定义MPI数据类型配合自定义归约操作实现结构体的全局归约,一次性拿到全局最大绝对值对应的完整结构体数据,实现步骤如下:
步骤1:为自定义结构体创建MPI数据类型
你定义的max_data结构体包含1个int型和2个double型字段,需要先向MPI描述该结构体的内存布局,创建对应的自定义MPI类型:
MPI_Datatype mpi_max_data; int block_len[3] = {1, 1, 1}; MPI_Aint displacements[3]; MPI_Datatype types[3] = {MPI_INT, MPI_DOUBLE, MPI_DOUBLE}; // 计算各字段相对于结构体起始地址的偏移 displacements[0] = offsetof(struct max_data, index); displacements[1] = offsetof(struct max_data, real_value); displacements[2] = offsetof(struct max_data, absolute_value); // 创建并提交自定义类型 MPI_Type_create_struct(3, block_len, displacements, types, &mpi_max_data); MPI_Type_commit(&mpi_max_data);
步骤2:实现自定义归约函数
按照MPI要求的签名实现归约逻辑,比较两个max_data实例的absolute_value字段,保留值更大的完整结构体即可:
void max_abs_reduce(void *in, void *inout, int *len, MPI_Datatype *dtype) { const struct max_data *in_arr = (const struct max_data *)in; struct max_data *inout_arr = (struct max_data *)inout; for (int i = 0; i < *len; i++) { if (in_arr[i].absolute_value > inout_arr[i].absolute_value) { inout_arr[i] = in_arr[i]; } } }
步骤3:注册自定义归约操作并执行Allreduce
将上述归约函数注册为MPI可识别的操作,替换你原来的普通数值归约即可:
// 注册自定义归约操作,第二个参数表示归约不区分前后顺序(可交换) MPI_Op max_abs_op; MPI_Op_create(max_abs_reduce, 1, &max_abs_op); // 每个进程先计算本地最大绝对值结构体 struct max_data local_max = find_max_absolute(local_result, size); struct max_data global_max; // 执行结构体级别的全局归约 MPI_Allreduce(&local_max, &global_max, 1, mpi_max_data, max_abs_op, MPI_COMM_WORLD); // 归约完成后释放资源 MPI_Op_free(&max_abs_op); MPI_Type_free(&mpi_max_data);
执行完成后所有进程的global_max就会是全局所有子数组中绝对值最大的那条完整记录,包含原始值、本地索引和绝对值信息。
注意:如果需要区分最大值属于哪个进程,可以在
max_data结构体中新增rank字段,更新自定义数据类型的定义,在本地计算local_max时填入当前进程的rank即可。
内容的提问来源于stack exchange,提问作者Albert Lorenzo
相关产品推荐
相关产品推荐

