并行编程——MPI 和OpenMPI 基本概念学习(一)
文章大纲引言一、MPI 概述二、MPI基础数据类型1、使用MPI_Type_create_struct创建结构体类型数据类型1.1、在C中定义结构体并确定成员偏移量1.2、创建自定义 MPI 数据类型2、使用MPI_Type_create_subarray创建子数组类型数据类型2.1、确定子数组的形状和位置2.2、创建自定义 MPI 数据类型三、通讯器communicator四、发送和接收五 、消息标签TAG 的使用六、MPI_Status 结构体https://github.com/mpitutorial/https://www.open-mpi.org/引言在 90 年代之前程序员可没我们这么幸运。对于不同的计算架构写并发程序是一件困难而且冗长的事情。当时很多软件库可以帮助写并发程序但是没有一个大家都接受的标准来做这个事情。在当时大多数的并发程序只出现在科学和研究的领域。最广为接受的模型就是消息传递模型指程序通过在进程间传递消息消息可以理解成带有一些信息和数据的一个数据结构来完成某些任务。举例来说主进程master process可以通过对从进程slave process发送一个描述工作的消息来把这个工作分配给它。另一个例子就是一个并发的排序程序可以在当前进程中对当前进程可见的我们称作本地的locally数据进行排序然后把排好序的数据发送的邻居进程上面来进行合并的操作。几乎所有的并行程序可以使用消息传递模型来描述。一、MPI 概述由于当时很多软件库都用到了这个消息传递模型但是在定义上有些微小的差异这些库的作者以及一些其他人为了解决这个问题就在 Supercomputing 1992 大会上定义了一个消息传递接口的标准也就是 MPI。这个标准接口使得程序员写的并发程序可以在所有主流的并发框架中运行。并且允许他们可以使用当时已经在使用的一些流行库的特性和模型。到 1994 年的时候一个完整的接口标准定义好了MPI-1。我们要记住 MPI 只是一个接口的定义而已。然后需要程序员去根据不同的架构去实现这个接口。很幸运的是仅仅一年之后一个完整的 MPI 实现就已经出现了。在第一个实现之后MPI 就被大量地使用在消息传递应用程序中并且依然是写这类程序的标准de-facto。MPI是一套定义了多个原语的消息传递接口这一接口主要被用于多进程间的通信。它的竞品包括 RPCDistributed Shared Memory 等二、MPI基础数据类型当然也支持创建自己的 MPI 数据类型来构建更复杂的消息类型。1、使用MPI_Type_create_struct创建结构体类型数据类型1.1、在C中定义结构体并确定成员偏移量//假设传递一个包含整数和浮点数的结构体structComplexData{intintegerPart;floatfloatPart;};然后需要确定每个成员在结构体中的偏移量偏移量是以字节为单位的距离从结构体的起始位置到成员的起始位置的距离。可以使用offsetof宏在stddef.h头文件中来计算偏移量。对于上述结构体整数部分的偏移量为 0 字节因为它是结构体的第一个成员浮点数部分的偏移量可以通过offsetof(struct ComplexData, floatPart)来计算得到的结果是sizeof(int)字节因为整数成员占sizeof(int)字节。1.2、创建自定义 MPI 数据类型使用MPI_Type_create_struct函数来创建自定义数据类型。这个函数的参数包括结构体成员的数量、每个成员的块长度对于基本类型通常为 1、每个成员的位移偏移量、每个成员的 MPI 数据类型以及一个用于存储新创建的数据类型的变量。MPI_Datatype customDataType;intblockLengths[2]{1,1};MPI_Aint displacements[2];MPI_Datatype types[2]{MPI_INT,MPI_FLOAT};displacements[0]0;displacements[1]sizeof(int);MPI_Type_create_struct(2,blockLengths,displacements,types,customDataType);MPI_Type_commit(customDataType);首先定义了数组blockLengths来表示每个成员的块长度都是 1displacements数组用于存储成员的偏移量types数组用于存储成员对应的 MPI 基本数据类型。然后调用MPI_Type_create_struct创建自定义数据类型customDataType最后通过MPI_Type_commit提交这个数据类型使其可以在 MPI 通信中使用。MPI_Send(complexData, 1, customDataType, destinationRank, tag, MPI_COMM_WORLD);MPI_Recv(receivedComplexData, 1, customDataType, sourceRank, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);2、使用MPI_Type_create_subarray创建子数组类型数据类型2.1、确定子数组的形状和位置假设要传递一个二维数组的子数组首先需要确定子数组在原始二维数组中的位置和形状。例如有一个int array[10][10]的二维数组要传递一个从array[3][3]开始形状为3x3的子数组。2.2、创建自定义 MPI 数据类型使用MPI_Type_create_subarray函数来创建子数组类型的数据类型。这个函数的参数包括数组的维度数、原始数组的形状以整数数组表示、子数组的形状以整数数组表示、子数组在原始数组中的起始位置以整数数组表示、数据的排列顺序如MPI_ORDER_C表示按行存储MPI_ORDER_FORTRAN表示按列存储以及一个用于存储新创建的数据类型的变量。例如intarraySizes[2]{10,10};intsubarraySizes[2]{3,3};intstarts[2]{3,3};MPI_Datatype subarrayDataType;MPI_Type_create_subarray(2,arraySizes,subarraySizes,starts,MPI_ORDER_C,MPI_INT,subarrayDataType);MPI_Type_commit(subarrayDataType);首先定义了原始数组的大小arraySizes、子数组的大小subarraySizes和子数组的起始位置starts然后调用MPI_Type_create_subarray创建自定义数据类型subarrayDataType最后通过MPI_Type_commit提交这个数据类型以便在 MPI 通信中用于传递子数组。简单使用自定义的数组MPI_Send(subarray, 1, subarrayDataType, destinationRank, tag, MPI_COMM_WORLD);MPI_Recv(receivedSubarray, 1, subarrayDataType, sourceRank, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);三、通讯器communicator通讯器定义了一组能够互相发消息的进程。在这组进程中每个进程会被分配一个序号称作秩rank进程间显性地通过指定秩来进行通信。通信的基础建立在不同进程间发送和接收操作。一个进程可以通过指定另一个进程的秩以及一个独一无二的消息标签tag来发送消息给另一个进程。接受者可以发送一个接收特定标签标记的消息的请求或者也可以完全不管标签接收任何消息然后依次处理接收到的数据。类似这样的涉及一个发送者以及一个接受者的通信被称作点对点point-to-point通信。四、发送和接收发送和接收是 MPI 里面两个基础的概念。MPI 里面几乎所有单个的方法都可以使用基础的发送和接收 API 来实现。MPI 的发送和接收方法是按以下方式进行的开始的时候A 进程决定要发送一些消息给 B 进程。A进程就会把需要发送给B进程的所有数据打包好放到一个缓存里面。因为所有数据会被打包到一个大的信息里面因此缓存常常会被比作信封就像我们把好多信纸打包到一个信封里面然后再寄去邮局。数据打包进缓存之后通信设备通常是网络就需要负责把信息传递到正确的地方。这个正确的地方也就是根据特定秩确定的那个进程。尽管数据已经被送达到 B 了但是进程 B 依然需要确认它想要接收 A 的数据。一旦它确定了这点数据就被传输成功了。进程 A 会接收到数据传递成功的信息然后去干其他事情。有时候 A 需要传递很多不同的消息给 B。为了让 B 能比较方便地区分不同的消息MPI 运行发送者和接受者额外地指定一些信息 ID (正式名称是标签, tags)。当 B 只要求接收某种特定标签的信息的时候其他的不是这个标签的信息会先被缓存起来等到 B 需要的时候才会给 B。MPI_Send(void*data,intcount,MPI_Datatype datatype,intdestination,inttag,MPI_Comm communicator)MPI_Recv(void*data,intcount,MPI_Datatype datatype,intsource,inttag,MPI_Comm communicator,MPI_Status*status)第一个参数是数据缓存。第二个和第三个参数分别描述了数据的数量和类型。MPI_send 会精确地发送 count 指定的数量个元素MPI_Recv 会最多接受 count 个元素第四个和第五个参数指定了发送方/接受方进程的秩以及信息的标签。第六个参数指定了使用的 communicator。第六个参数指定了使用的 communicator。MPI_Recv 方法特有的最后一个参数提供了接受到的信息的状态。五 、消息标签TAG 的使用六、MPI_Status 结构体前面仅仅只介绍了如何发送事先知道消息长度的消息。尽管可以将消息的长度作为单独的发送/接收操作发送但是 MPI 本身仅通过几个额外的函数调用即可支持动态消息。MPI_Recv 将 MPI_Status 结构体的地址作为参数可以使用 MPI_STATUS_IGNORE 忽略。 如果我们将 MPI_Status 结构体传递给 MPI_Recv 函数则操作完成后将在该结构体中填充有关接收操作的其他信息。 三个主要的信息包括发送端秩发送端的秩存储在结构体的 MPI_SOURCE 元素中。也就是说如果我们声明一个 MPI_Status stat 变量则可以通过 stat.MPI_SOURCE 访问秩。消息的标签消息的标签可以通过结构体的 MPI_TAG 元素访问类似于 MPI_SOURCE。消息的长度 消息的长度在结构体中没有预定义的元素。但我们可使用 MPI_Get_count 找出消息的长度。//MPI_Get_count 函数中使用者需要传递 MPI_Status 结构体消息的 datatype数据类型并返回 count。 变量 count 是已接收的 datatype 元素的数目。MPI_Get_count(MPI_Status*status,MPI_Datatype datatype,int*count)//MPI_Get_count 的返回值是相对于传递的数据类型而言的。 如果用户使用 MPI_CHAR 作为数据类型则返回的数量将是原来的四倍假设整数是四个字节而 char 是一个字节MPI_Recv 可以将 MPI_ANY_SOURCE 用作发送端的秩将 MPI_ANY_TAG 用作消息的标签。 在这种情况下MPI_Status 结构体是找出消息的实际发送端和标签的唯一方法。 此外并不能保证 MPI_Recv 能够接收函数调用参数的全部元素。 相反它只接收已发送给它的元素数量如果发送的元素多于所需的接收数量则返回错误。 MPI_Get_count 函数用于确定实际的接收量未完待续…

相关新闻

syzkaller 依赖的 errchkjson 静态分析器:json.Marshal 错误处理与类型安全分类详解

syzkaller 依赖的 errchkjson 静态分析器:json.Marshal 错误处理与类型安全分类详解

测试操作系统网络安全 【免费下载链接】syzkaller syzkaller is an unsupervised coverage-guided kernel fuzzer 项目地址: https://gitcode.com/gh_mirrors/syz/syzkaller 点击查看 免费下载 本文围绕 syzkaller 仓库中 vendor 目录下的 errchkjson 文档展开&…

2026/10/14 1:53:15 阅读更多 →
Farm 懒编译(Lazy Compilation)实战指南:让大型项目开发编译从分钟级降到秒级

Farm 懒编译(Lazy Compilation)实战指南:让大型项目开发编译从分钟级降到秒级

前端构建构建工具开发工具 【免费下载链接】farm Extremely fast Vite-compatible web build tool written in Rust 项目地址: https://gitcode.com/gh_mirrors/fa/farm 点击查看 免费下载 Farm 是一款用 Rust 编写的 Vite 兼容 Web 构建工具,其「懒编译…

2026/10/14 1:53:15 阅读更多 →
TEngine 设计模式应用剖析:单例、工厂、观察者与状态机的工业化实现

TEngine 设计模式应用剖析:单例、工厂、观察者与状态机的工业化实现

游戏开发 【免费下载链接】TEngine Unity 商用级别开发框架,原生内置 AI 工作流支持,集成 HybridCLR 高性能热更、Obfuz 代码混淆加固、YooAssets 企业级资源管理方案,构建高效、安全、可扩展的工业化开发底座。 项目地址: https:…

2026/10/14 1:53:15 阅读更多 →

最新新闻

Vue 3 轻量级数据透视表组件:支持拖拽+聚合+Excel导出

Vue 3 轻量级数据透视表组件:支持拖拽+聚合+Excel导出

简介:这是一份面向Vue.js中高级开发者的数据透视表功能实现组件包,专为需要在Web应用中快速集成交互式聚合分析表格的前端工程师设计。资源提供两个核心Vue组件:支持拖放配置行列的完整数据透视表,以及轻量级仅聚合功能的PivotTab…

2026/10/14 2:45:28 阅读更多 →
CLRS 习题精解:B 树基本操作(B-TREE-INSERT、查找最值与前驱)与复杂度分析

CLRS 习题精解:B 树基本操作(B-TREE-INSERT、查找最值与前驱)与复杂度分析

文档教程教育 【免费下载链接】CLRS 📚 Solutions to Introduction to Algorithms Third Edition 项目地址: https://gitcode.com/gh_mirrors/clr/CLRS 点击查看 免费下载 本文以《算法导论(第三版)》第 18 章 18.2 节"B 树…

2026/10/14 2:45:28 阅读更多 →
加班后的回程路上,更适合先听完《妈妈,我失业了》

加班后的回程路上,更适合先听完《妈妈,我失业了》

傍晚下班路上,中学生,把耳机音量调到刚好盖住走廊声在便利店门口抽一口冷气再进门。歌词里「走不出了」写的就是这种说不清又不甘心的时刻——《妈妈,我失业了》接住的,正是这截情绪。词曲:小熊歌|演唱&…

2026/10/14 2:45:28 阅读更多 →
【Python实战】基于FastAPI的绿植养护管理系统 - 完整项目

【Python实战】基于FastAPI的绿植养护管理系统 - 完整项目

🥂(❁◡❁)您的点赞👍➕评论📝➕收藏⭐➕关注👀是作者创作的最大动力🤞 💖📕🎉🔥 支持我:点赞👍收藏⭐️留言📝关注👀欢迎…

2026/10/14 2:45:28 阅读更多 →
Cap 开源录屏上手:从依赖自检到发出第一条分享链接

Cap 开源录屏上手:从依赖自检到发出第一条分享链接

Cap 开源录屏上手:从依赖自检到发出第一条分享链接 【免费下载链接】Cap Open source Loom alternative. Beautiful, shareable screen recordings. 项目地址: https://gitcode.com/GitHub_Trending/cap1/Cap 给同事讲一个功能,你得先凑齐三人的日…

2026/10/14 2:45:28 阅读更多 →
单片机毕设选题推荐:基于STM32的婴儿摇篮哭泣尿床监测与环境联动控制系统设计 基于物联网的婴儿床温湿度自动调节与哄睡装置设计(032707)

单片机毕设选题推荐:基于STM32的婴儿摇篮哭泣尿床监测与环境联动控制系统设计 基于物联网的婴儿床温湿度自动调节与哄睡装置设计(032707)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/10/14 2:44:28 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →