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 系列学习(-) 数据类型
数据类型的出现 在的编程语言中,数据类型用于声明函数和变量,数据类型的出现是为了要把数据分成数据所需要内存大小的不同数据,编程时需要什么样的内存就申请什么样的内存.就可以充分的利用内存,更好的霸控程序 ...
随机推荐
- codeforce——因数筛
题目大意:给你一个 n 和 k 求 n 的第 k 个因数. #include<iostream> #include <algorithm> #include <queue ...
- echarta3 北京,上海地图
1.首先你得到echarts官网下载js,建议下载完整代码,这样你就很容易根据我的路径找到beijing.js 2.把echarts.js和beijingi.js根据你的路径引对,然后就可以copy我 ...
- kmp&扩展kmp
kmp: KMP的主要目的是求B是不是A的子串,以及若是,B在A中所有出现的位置 写的很详细的大佬的博客:http://www.matrix67.com/blog/archives/115 模板: / ...
- 爬虫框架:scrapy
一 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前Scrapy的用途十分广泛,可 ...
- 硬盘安装CentOS 6.0(超级详细图文教程)
硬盘安装CentOS 6.0(超级详细图文教程) 来源: 引言: 电脑系统是Windows XP,电脑没有光驱.手头没有U盘.没有移动硬盘.电脑主板不支持U盘启动,在这种情况下想安装CentOS ...
- Junit4与junt3并存时产生的问题
目前的项目里用junit写单元测试,使用的是junit4,由于大部分开发之前使用的都是junit3,对junit4还不是很熟悉,所以出现了junit3和4混合使用的情况,导致发生了一些问题,这里列举一 ...
- 【LeetCode 36_哈希表】Valid Sudoku
//occupyed_1检查行是否占用 //occupyed_2检查列是否占用 //occupyed_3检查块是否占用 bool isValidSudoku(vector<vector<c ...
- 装载Properties资源文件的项目中使用
ssm项目中打算将发短信的每小时每天的限定变成可配置的.于是将配置信息写在资源文件中,现在有两种方式加载资源文件,一个是使用spring注入方式,@Value注解注入,当然,前面需要在项目中装载.第二 ...
- selenium对应三大浏览器(谷歌、火狐、IE)驱动安装
selenium:v3.7.0 一.谷歌浏览器 chromdriver.exe 根据自己谷歌浏览器版本安装对应chromedriver的版本. 我电脑谷歌版本是65的,装的v2.36版,链接:http ...
- wbr 视机而动
链接 在适当的时候, 除非能容下整个单车, 才保留一行: 缩放浏览器, 试试这段就知道了 <p>To learn AJAX, you must be familiar with the X ...