MPI 派生数据类型 MPI_Type_create_struct(),MPI_Type_contiguous(),MPI_Type_vector(),MPI_Type_create_hvector(),MPI_Type_indexed()
▶ 使用 MPI 派生数据类型,减少数据在传输过程中的耗时
● MPI_Type_create_struct() 范例代码
{
const int globalSize = ;
int globalDataInt[globalSize], globalDataDouble[globalSize];
int i, comSize, comRank, randomInt, sumInt;
double sumDouble;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &comSize);
MPI_Comm_rank(MPI_COMM_WORLD, &comRank);
// 创建派生数据类型,包含 1 个整形数组,1 个浮点数组和 1 个整形的结构。创建过程只与数据类型有关而与数据的值无关,每个进程都进行了创建
int blockLength[] = { globalSize,globalSize, }; // 各成员的长度
MPI_Aint globalDataInt_p, globalDataDouble_p, randomInt_p; // 获取各成员的地址,以计算偏移量
MPI_Get_address((void *)globalDataInt, &globalDataInt_p);
MPI_Get_address((void *)globalDataDouble, &globalDataDouble_p);
MPI_Get_address((void *)&randomInt, &randomInt_p);
MPI_Aint displacement[] = { , globalDataDouble_p - globalDataInt_p,randomInt_p - globalDataInt_p };// 计算各成员地址关于第一个成员的偏移量
int type[] = { MPI_INT,MPI_DOUBLE,MPI_INT }; // 各成员的数据类型
MPI_Datatype newType; // 调用内建函数创建新类型
MPI_Type_create_struct(, blockLength, displacement, type, &newType);
MPI_Type_commit(&newType); // 提交新类型,以便像 MPI_Datatype 那样使用
if (comRank == )
{
for (i = ; i < globalSize; globalDataInt[i] = i, globalDataDouble[i] = (double)i, i++);
randomInt = ;
}
MPI_Bcast(globalDataInt, , newType, , MPI_COMM_WORLD);// 发送数据到各进程,使用的数据指针是派生数据类型中首个成员的数据的指针
for (i = sumInt = , sumDouble = 0.0; i < globalSize; i++)
{
sumInt += globalDataInt[i];
sumDouble += globalDataDouble[i];
}
printf("Size = %d, rank = %d, resultInt = %d, resultDouble = %f, randomInt = %d\n", comSize, comRank, sumInt, sumDouble, randomInt);
MPI_Type_free(&newType);
MPI_Finalize();
return ;// 输出结果:八个进程乱序输出诸如 Size = 8, rank = 4, resultInt = 28, resultDouble = 28.000000, randomInt = 120994 的结果
}
● 用到的函数
// 创建派生数据类型
MPI_METHOD MPI_Type_create_struct(
_In_range_(>= , ) int count, // 成员个数
_mpi_reads_(count) const int array_of_blocklengths[], // 各成员的长度,1 为标量,大于 1 为矢量
_mpi_reads_(count) const MPI_Aint array_of_displacements[], // 各成员地址关于第一个成员的偏移量,以便 MPI 整合数据
_mpi_reads_(count) const MPI_Datatype array_of_types[], // 成员数据类型
_Out_ MPI_Datatype* newtype // 传入一个 MPI_Datatype* 类型的指针,用于输出所创建的类型
); // 提交创建的数据类型以便使用
MPI_METHOD
MPI_Type_commit(_In_ MPI_Datatype* datatype);// 传入使用函数 MPI_Type_create_struct() 创建的类型,之后就能像使用 MPI_Datatype 那样使用创建的数据类型了 MPI_METHOD MPI_Type_free(_Deref_out_range_(== , MPI_DATATYPE_NULL) _Inout_ MPI_Datatype* datatype);
// 使用自定义的类型需要额外的空间开销,是使用完毕后要释放空间,需要传入创建个点类型
▶ 其他几个派生数据类型的函数原型
MPI_METHOD MPI_Type_contiguous(
_In_range_(>= , ) int count, // 数据个数
_In_ MPI_Datatype oldtype, // 原数据类型
_Out_ MPI_Datatype* newtype // 新数据名
); MPI_METHOD MPI_Type_vector(
_In_range_(>= , ) int count, // 数据个数
_In_range_(>= , ) int blocklength, // 每个数据的宽度(即每个数据本身可以是一个矢量)
_In_ int stride, // 相邻数据之间的跨步(&a[n+1] - &a[n],a[n] 内部不是什么不重要)
_In_ MPI_Datatype oldtype, // 原数据类型
_Out_ MPI_Datatype* newtype // 新数据名
); MPI_METHOD MPI_Type_create_hvector(
_In_range_(>= , ) int count, // 元素个数
_In_range_(>= , ) int blocklength, // 元素宽度(个数为单位)
_In_ MPI_Aint stride, // 相邻元素跨度(字节为单位)
_In_ MPI_Datatype oldtype, // 原数据类型
_Out_ MPI_Datatype* newtype // 新数据名
); MPI_METHOD MPI_Type_indexed(
_In_range_(>=, ) int count, // 元素个数
_mpi_reads_(count) const int array_of_blocklengths[], // 元素宽度
_mpi_reads_(count) const int array_of_displacements[], // 每个元素关于首元的偏移量
_In_ MPI_Datatype oldtype, // 原数据类型
_Out_ MPI_Datatype* newtype // 新数据名
);
● 函数 MPI_Type_contiguous() 和 MPI_Type_vector() 范例
// 将整形数组中连续 7 个元素封装为一个 newType 进行消息传递
{
MPI_Datatype newType;
MPI_Type_contiguous(, MPI_INT, &newType);
MPI_Type_commit(&newType);
} // 将二维数组 a[11][13] 中某两列前 7 个元素封装为一个 newType 进行消息传递
{
MPI_Datatype newType;
MPI_Type_vector(, , , MPI_INT, &newType);// 注意每个元素宽度为 2,跨度为 13(即一行的元素个数)
MPI_Type_commit(&newType);
}
● 函数 MPI_Type_create_hvector() 的范例
{
const int dataSize = ;
MPI_Datatype int3, type;
int comRank, comSize, i, data[dataSize];
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &comSize);
MPI_Comm_rank(MPI_COMM_WORLD, &comRank);
MPI_Type_contiguous(, MPI_INT, &int3);// 连续三个整形组一个 int3
MPI_Type_commit(&int3);
MPI_Type_create_hvector(, , * sizeof(int), int3, &type);// 一个 type 包含 3 个元素,每个元素由连续两个 int3 组成,3 个元素之间跨度为 7 个整形
MPI_Type_commit(&type);
if (comRank == )// 0 号进程发送一个 type 给 1 号进程
{
for (i = ; i < dataSize; data[i] = i, i++);
MPI_Send(data, , type, ,, MPI_COMM_WORLD);
}
if (comRank == )
{
for (i = ; i < dataSize; data[i++] = -);
MPI_Recv(data, , type, , , MPI_COMM_WORLD,MPI_STATUS_IGNORE);
for (i = ; i < dataSize; i++)
printf("%3d, ", data[i]);
fflush(stdout);
}
MPI_Finalize();
return ;
}
● 输出结果,连续 6 个元素断一下
D:\Code\MPI\MPIProjectTemp\x64\Debug>mpiexec -n -l MPIProjectTemp.exe
[] , , , , , , -, , , , , , , -, , , , , , , -,
● 函数 MPI_Type_indexed() 范例
{
const int dataSize = ;
MPI_Datatype int3, type;
int comRank, comSize, i, data[dataSize], blocklen[] = { , , }, displacement[] = { , , };
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &comSize);
MPI_Comm_rank(MPI_COMM_WORLD, &comRank);
MPI_Type_contiguous(, MPI_INT, &int3);
MPI_Type_commit(&int3);
MPI_Type_indexed(, blocklen, displacement, int3, &type);// 一个 type 包含 3 个元素,每个元素分别由 blocklen[i] 个 int3 组成,各元素之间跨度为 displacement[i] 个 int3 形
MPI_Type_commit(&type);
if (comRank == )
{
for (i = ; i < dataSize; data[i] = i, i++);
MPI_Send(data, , type, , , MPI_COMM_WORLD);
}
if (comRank == )
{
for (i = ; i < dataSize; data[i++] = -);
MPI_Recv(data, , type, , , MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
for (i = ; i<dataSize; i++)
printf("%3d, ", data[i]);
fflush(stdout);
}
MPI_Finalize();
return ;
}
● 输出结果,分别为 6 个、9 个、3 个元素,偏移位置分别为第 0,3,8 个 int3 的起点位置
D:\Code\MPI\MPIProjectTemp\x64\Debug>mpiexec -n -l MPIProjectTemp.exe
[] , , , , , , -, -, -, , , , , , , , , , -, -, -, -, -, -, , , ,
▶ 其他派生数据类型,等待补全
MPI_METHOD MPI_Type_create_hindexed(
_In_range_(>= , ) int count,
_mpi_reads_(count) const int array_of_blocklengths[],
_mpi_reads_(count) const MPI_Aint array_of_displacements[],
_In_ MPI_Datatype oldtype,
_Out_ MPI_Datatype* newtype
); MPI_METHOD MPI_Type_create_hindexed_block(
_In_range_(>= , ) int count,
_In_range_(>= , ) int blocklength,
_mpi_reads_(count) const MPI_Aint array_of_displacements[],
_In_ MPI_Datatype oldtype,
_Out_ MPI_Datatype* newtype
); MPI_METHOD MPI_Type_create_indexed_block(
_In_range_(>= , ) int count,
_In_range_(>= , ) int blocklength,
_mpi_reads_(count) const int array_of_displacements[],
_In_ MPI_Datatype oldtype,
_Out_ MPI_Datatype* newtype
); MPI_METHOD MPI_Type_create_subarray(
_In_range_(>= , ) int ndims,
_mpi_reads_(ndims) const int array_of_sizes[],
_mpi_reads_(ndims) const int array_of_subsizes[],
_mpi_reads_(ndims) const int array_of_starts[],
_In_range_(MPI_ORDER_C, MPI_ORDER_FORTRAN) int order,
_In_ MPI_Datatype oldtype,
_Out_ MPI_Datatype* newtype
); _Pre_satisfies_(order == MPI_DISTRIBUTE_DFLT_DARG || (order >= MPI_DISTRIBUTE_BLOCK && order <= MPI_DISTRIBUTE_NONE))
MPI_METHOD MPI_Type_create_darray(
_In_range_(>= , ) int size,
_In_range_(>= , ) int rank,
_In_range_(>= , ) int ndims,
_mpi_reads_(ndims) const int array_of_gsizes[],
_mpi_reads_(ndims) const int array_of_distribs[],
_mpi_reads_(ndims) const int array_of_dargs[],
_mpi_reads_(ndims) const int array_of_psizes[],
_In_ int order,
_In_ MPI_Datatype oldtype,
_Out_ MPI_Datatype* newtype
);
MPI 派生数据类型 MPI_Type_create_struct(),MPI_Type_contiguous(),MPI_Type_vector(),MPI_Type_create_hvector(),MPI_Type_indexed()的更多相关文章
- MPI自定义数据类型
自定义数据类型 1.数据类型辅助函数 MPI_Type_commit int MPI_Type_commit( MPI_Datatype *datatype ); 在通信中使用数据类型对象之前,必须提 ...
- MPI n 体问题
▶ <并行程序设计导论>第六章中讨论了 n 体问题,分别使用了 MPI,Pthreads,OpenMP 来进行实现,这里是 MPI 的代码,分为基本算法和简化算法(引力计算量为基本算法的一 ...
- 【MPI学习6】MPI并行程序设计模式:具有不连续数据发送的MPI程序设计
基于都志辉老师<MPI并行程序设计模式>第14章内容. 前面接触到的MPI发送的数据类型都是连续型的数据.非连续类型的数据,MPI也可以发送,但是需要预先处理,大概有两类方法: (1)用户 ...
- XML学习笔记5——XSD复杂数据类型
和简单数据类型对应就是复杂数据类型了,XML元素的数据类型可以是简单数据类型,也可以是复杂数据类型,而XML属性的数据类型就只能是简单数据类型.这篇笔记,就来学习一下XSD中的复杂数据类型了. 1.定 ...
- C语言中的数据类型
基本数据类型: int float double char void 派生数据类型: 数据类型修饰符 + 基本数据类型 = 派生数据类型 signed 和 unsigned 类型 unsigned ...
- MPI Hello World
▶<并行程序设计导论>第三章(用 MPI 进行分布式内存编程)的第一个程序样例. ● 代码 #include <stdio.h> #include <string.h& ...
- xml schema数据类型
1.简单数据类型 (1)内置简单数据类型 schema中定义了一些简单数据类型,包括primitive原始数据类型和derived派生数据类型,这些类型都是schema中使用的 最基本的数据类型,我们 ...
- go语言-数据类型及类型之间转换
数据类型分类 一.数据类型-基本数据类型 1.整数型(int.有符号(int8/1字节.int16/2字节.int32/4字节.int64/8字节).无符号(uint.uint8.uint16.uin ...
- golang 系列学习(-) 数据类型
数据类型的出现 在的编程语言中,数据类型用于声明函数和变量,数据类型的出现是为了要把数据分成数据所需要内存大小的不同数据,编程时需要什么样的内存就申请什么样的内存.就可以充分的利用内存,更好的霸控程序 ...
随机推荐
- 获取文本中所有的<img>标签的位置,获取所有img标签的src
public static int[] GetImagePos(string str) { str = str.Replace("$", " "); str = ...
- Linux 下升级JDK 1.7到1.8
1.下载1.8的jdk rpm文件到linux系统 2.执行rpm -ivh jdk-8u151-linux-x64.rpm 选项详解: -a:查询所有套件: -b<完成阶段><套件 ...
- powerdesigner安装图解
- bzoj1224
题解: 暴力+剪纸 判断一下最大行不行,最小行不行 代码: #include<bits/stdc++.h> ; using namespace std; ],q; int n,m,x,y, ...
- 如何导入数据到Mysql
有两种方法: 1.如果是.sql后缀的数据库文件,使用phpmyadmin中的导入功能导入即可,导入前需要新建数据库名. 2.如果导入的是文件夹(内含.frm,.myd,.myi,.opt类型文件), ...
- Hadoop1.1.2伪分布式安装
一.安装前准备设置Linux的静态IP修改VirtualBox的虚拟网卡地址修改主机名把hostname和ip绑定关闭防火墙:service iptables stop二.SSH免密码登陆生成秘钥文件 ...
- 免费180天的Ashampoo Anti-Virus 2014
官方网站:https://www.ashampoo.com/cn/rmb/pde/0449/Security_Software/Ashampoo-Anti-Virus 活动页面:http://www. ...
- 5.5修改xadmin的头部底部和导航栏名称
1.修改xadmin的头部标题和底部信息: 在users模块中的adminx.py中添加修改函数: from xadmin import views class GlobalSettings(obje ...
- sqlite常用语法详细介绍
1.SQL语句的预编译:将语句转为数据流,执行语句前检查语句的语法,但不能知道语句是否能查出结果.此方法有返回值 预编译成功则返回SQLITE_OK----0否则返回SQLITE_ERROR---- ...
- 第10课 struct和union分析
struct的小秘密:空结构体占多大内存呢? 直观的答案有两种: 1.空结构体的大小为0 2.结构体本来就是为了将不同的变量集合在一起使用的,定义空结构体会导致编译错误 实例分析: #include ...