C++进程链接工具之通信器详解

目录
  • 一、传播者
  • 二、示例和代码

一、传播者

本章中的所有示例仅使用一个连接所有进程的通信器。但是,可以创建更多的通信器来链接进程的子集。这对于不需要由所有进程执行的集体操作特别有用。

二、示例和代码

示例 47.15。使用多个通信器

#include <boost/mpi.hpp>
#include <boost/serialization/string.hpp>
#include <string>
#include <iostream>
int main(int argc, char *argv[])
{
  boost::mpi::environment env{argc, argv};
  boost::mpi::communicator world;
  boost::mpi::communicator local = world.split(world.rank() < 2 ? 99 : 100);
  std::string s;
  if (world.rank() == 0)
    s = "Hello, world!";
  boost::mpi::broadcast(local, s, 0);
  std::cout << world.rank() << ": " << s << '\n';
}

Example47.15

示例 47.15 使用函数 boost::mpi::broadcast()。此函数发送字符串“Hello, world!”从等级为 0 的进程到链接到本地​​通信器的所有进程。等级为 0 的进程也必须链接到该通信器。

本地通信器是通过调用 split() 创建的。 split() 是在全局通信器世界上调用的成员函数。 split() 需要一个整数来将进程链接在一起。将相同整数传递给 split() 的所有进程都链接到相同的通信器。传递给 split() 的整数值无关紧要。重要的是应该由特定通信器链接的所有进程都传递相同的值。

在示例 47.15 中,等级为 0 和 1 的两个进程将 99 传递给 split()。如果程序启动时有两个以上的进程,则额外的进程会传递 100。这意味着前两个进程有一个本地通信器,所有其他进程都有另一个本地通信器。每个进程都链接到 split() 返回的通信器。是否有其他进程链接到同一个通信器取决于其他进程是否将相同的整数传递给 split()。

请注意,等级始终与传播者有关。最低等级始终为 0。在示例 47.15 中,相对于全局通信器具有等级 0 的进程相对于其本地通信器也具有等级 0。相对于全局通信器具有等级 2 的进程相对于其本地通信器具有等级 0。

如果您使用两个或更多进程启动示例 47.15,您好,世界!将显示两次 - 每次由相对于全局通信器的等级为 0 和 1 的进程显示一次。因为 s 设置为“Hello, world!”仅在全局等级为 0 的进程中,此字符串仅通过通信器发送到链接到同一通信器的那些进程。这只是具有全局排名 1 的进程,这是唯一将 99 传递给 split() 的其他进程。

示例 47.16。使用组对流程进行分组

#include <boost/mpi.hpp>
#include <boost/serialization/string.hpp>
#include <boost/range/irange.hpp>
#include <boost/optional.hpp>
#include <string>
#include <iostream>
int main(int argc, char *argv[])
{
  boost::mpi::environment env{argc, argv};
  boost::mpi::communicator world;
  boost::mpi::group local = world.group();
  boost::integer_range<int> r = boost::irange(0, 1);
  boost::mpi::group subgroup = local.exclude(r.begin(), r.end());
  boost::mpi::communicator others{world, subgroup};
  std::string s;
  boost::optional<int> rank = subgroup.rank();
  if (rank)
  {
    if (rank == 0)
      s = "Hello, world!";
    boost::mpi::broadcast(others, s, 0);
  }
  std::cout << world.rank() << ": " << s << '\n';
}

MPI 支持分组进程。这是在类 boost::mpi::group 的帮助下完成的。如果您在通信器上调用成员函数 group(),则链接到通信器的所有进程都将在类型为 boost::mpi::group 的对象中返回。您不能使用此对象进行通信。它只能用于形成一组新的进程,然后可以从中创建通信器。

boost::mpi::group 提供成员函数,如 include() 和 exclude()。您传递迭代器以包含或排除进程。 include() 和 exclude() 返回一个类型为 boost::mpi::group 的新组。

示例 47.16 将两个迭代器传递给 exclude(),它们引用类型为 boost::integer_range 的对象。该对象表示一个整数范围。它是在函数 boost::irange() 的帮助下创建的,它需要一个下限和上限。上限是一个不属于该范围的整数。在此示例中,这意味着 r 仅包含整数 0。

调用 exclude() 会导致创建子组,其中包含除等级为 0 的进程之外的所有进程。然后使用该组创建一个新的通信器 others。这是通过将全局通信器世界和子组传递给 boost::mpi::communicator 的构造函数来完成的。

请注意,others 是一个 communicator,它在 rank 0 的进程中是空的。rank 0 的进程没有链接到这个 communicator,但是变量 others 仍然存在于这个进程中。您必须注意不要在此过程中使用其他人。示例 47.16 通过在子组上调用 rank() 来防止这种情况。成员函数在不属于该组的进程中返回一个类型为 boost::optional 的空对象。其他进程接收它们相对于该组的等级。

如果 rank() 返回排名并且没有类型为 boost::optional 的空对象,则调用 boost::mpi::broadcast()。等级为 0 的进程发送字符串“Hello, world!”链接到其他通信器的所有进程。请注意,等级是相对于那个传播者的。相对于其他进程排名为 0 的进程相对于全球通信者世界排名为 1。

如果您使用两个以上的进程运行示例 47.16,则全局等级大于 0 的所有进程都将显示 Hello, world!。

到此这篇关于C++进程链接工具之通信器详解的文章就介绍到这了,更多相关C++通信器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2022-11-18

C++通信新特性协程详细介绍

目录 一.关于协程 二.协程的好处 三.协程得用法 四.与线程的区别 五.协程示例 一.关于协程 从 1.54.0 版本开始,Boost.Asio 支持协程.虽然您可以直接使用 Boost.Coroutine,但 Boost.Asio 中对协程的显式支持使得使用它们变得更加容易. 协程让您创建一个反映实际程序逻辑的结构.异步操作不会拆分函数,因为没有处理程序来定义异步操作完成时应该发生什么.程序可以使用顺序结构,而不是让处理程序相互调用. 二.协程的好处 考虑多任务协作的场景. 如果是线程的并发

C++&nbsp;实现即时通信的示例代码(直接运行)

目录 题目 软件:VS 服务器端 客户端 题目 由于本学期上了网络编程课程,老师要求写使用Socke实现网络编程.于是参考C++多线程实现即时通信软件写出了简单版本的没有界面的即时通信软件. 软件:VS 直接上代码,需要讲解原理的,可以参考C++多线程实现即时通信软件 服务器端 //TcpServer_plus.exe #include<stdio.h> #include <Winsock2.h> #include<WS2tcpip.h> #pragma comment

C++&nbsp;Thread实现简单的socket多线程通信

目录 起因 服务端 ROS客户端 普通客户端 运行效果 不足 起因 为什么要用C++的Thread,很简单,因为我菜 一打五用pthread实现了socket多线程通信,我之前学并发的时候没看pthread,因此代码只能看个大概,后面还是要系统学一下pthread的 服务端 多线程功能放在腾讯云服务器上,代码如下: #include "tcpserver.h" #include <thread> #include <mutex> TcpServer server

C++多线程实现TCP服务器端同时和多个客户端通信

通讯建立后首先由服务器端发送消息,客户端接收消息:接着客户端发送消息,服务器端接收消息,实现交互发送消息. 服务器同时可以和多个客户端建立连接,进行交互: 在某次交互中,服务器端或某客户端有一方发送"end"即终止服务器与其的通信:服务器还可以继续接收其他客户端的请求,与其他客户端通信. 服务器端 #include <WinSock2.h> #include <WS2tcpip.h> #include <iostream> using namespa

C++广播通信实例

本文实例讲述了C++实现广播通信的方法.分享给大家供大家参考.具体实现方法如下: 广播通信代码框架: 1. 协议都是: 复制代码 代码如下: SOCKET s = ::socket(AF_INET, SOCK_DGRAM, 0); 2. 服务端设置选项 复制代码 代码如下: BOOL bBroadcast = TRUE;  ::setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&bBroadcast, sizeof(BOOL)); 3. 服务端向255

C++基于boost&nbsp;asio实现sync&nbsp;tcp&nbsp;server通信流程详解

目录 一.功能介绍 二.string类型数据交互 2.1 程序源码 2.2 编译&&执行 2.3 程序执行结果 三.byte类型数据交互 3.1 程序源码 3.2 编译&&执行 3.3 程序执行结果 一.功能介绍   基于boost asio实现server端通信,采用one by one的同步处理方式,并且设置连接等待超时.下面给出了string和byte两种数据类型的通信方式,可覆盖基本通信场景需求. 二.string类型数据交互   规定server与client双方

C++线程间的互斥和通信场景分析

互斥锁(mutex) 为了更好地理解,互斥锁,我们可以首先来看这么一个应用场景:模拟车站卖票. 模拟车站卖票 场景说明: Yang车站售卖从亚特兰蒂斯到古巴比伦的时光飞船票:因为机会难得,所以票数有限,一经发售,谢绝补票. 飞船票总数:100张: 售卖窗口:3个. 对于珍贵的飞船票来说,这个资源是互斥的,比如第100张票,只能卖给一个人,不可能同时卖给两个人.3个窗口都有权限去售卖飞船票(唯一合法途径). 不加锁的结果 根据场景说明,我们可以很快地分析如下: 可以使用三个线程来模拟三个独立的窗口

浅析C\C++和Lua的通信方式

为了实现Lua和其他语言之间的通信,Lua虚拟机为C\C++提供了两个特性: 一,Lua_State状态机 lua_State主要是管理一个lua虚拟机的执行环境, 一个lua虚拟机可以有多个执行环境.Lua虚拟机通过维护这样一个虚拟栈来实现两种之间的通信,lua_State定义如下: struct lua_State { CommonHeader; lu_byte status; StkId top; /* first free slot in the stack */ global_Stat

C++详细分析线程间的同步通信

目录 1.多线程编程两个问题 1.1.线程间的互斥 1.2.线程间的同步通信 2.生产者-消费者线程模型 3.lock_gard和unique_lock 4.流程分析 1.多线程编程两个问题 1.1.线程间的互斥 竞态条件: 多线程执行的结果是一致的,不会随着CPU对线程不同的调用顺序,而产生不同的运行结果. 发生竞态条件的代码段,称为临界区代码段(只有一个线程可以进来),保证临界区代码段原子操作,通过线程互斥锁mutex,也可以使用轻量级的无锁实现CAS. C++11的mutex底层实现: 使

java线程池的四种创建方式详细分析

目录 前言 1. 线程池 2. 创建方式 前言 在讲述线程池的前提 先补充一下连接池的定义 连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用 可以看到其连接池的作用如下: 1. 线程池 线程池(英语:thread pool):一种线程使用模式.线程过多会带来调度开销,进而影响缓存局部性和整体性能.而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务.这避免了在处理短时间任务时创建与销毁线程的代价.线程池不仅能够保证内核的充分利用,还能防止过分调度 特点:

详细分析JAVA 线程池

系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互.在这种情形下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池. 与数据库连接池类似的是,线程池在系统启动时即创建大量空闲的线程,程序将一个 Runnable 对象或 Callable 对象传给线程池,线程池就会启动一个线程来执行它们的 run() 或 call() 方法,当 run() 或 call() 方法执行结束后,该线程并不会死亡,而是再次返回线程池成为空闲状态,等待执行下一个

java线程池核心API源码详细分析

目录 概述 源码分析 Executor ExecutorService ScheduledExecutorService ThreadPoolExecutor ScheduledThreadPoolExecutor 总结 概述 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中.如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有

非常适合新手学生的Java线程池超详细分析

目录 线程池的好处 创建线程池的五种方式 缓存线程池CachedThreadPool 固定容量线程池FixedThreadPool 单个线程池SingleThreadExecutor 定时任务线程池ScheduledThreadPool ThreadPoolExecutor创建线程池(十分推荐) ThreadPoolExecutor的七个参数详解 workQueue handler 如何触发拒绝策略和线程池扩容? 线程池的好处 可以实现线程的复用,避免重新创建线程和销毁线程.创建线程和销毁线程对

详细分析java线程wait和notify

wait()和notify()是直接隶属于Object类,也就是说,所有对象都拥有这一对方法.初看起来这十分 不可思议,但是实际上却是很自然的,因为这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放.而调用任意对象的notify()方法则导致因调用该对象的wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行). 其次,wait()和notify()可在任何位置调用,但是这一对方法却必须在

基于Java 生产者消费者模式(详细分析)

生产者消费者模式是多线程中最为常见的模式:生产者线程(一个或多个)生成面包放进篮子里(集合或数组),同时,消费者线程(一个或多个)从篮子里(集合或数组)取出面包消耗.虽然它们任务不同,但处理的资源是相同的,这体现的是一种线程间通信方式. 本文将先说明单生产者单消费者的情况,之后再说明多生产者多消费者模式的情况.还会分别使用wait()/nofity()/nofityAll()机制.lock()/unlock()机制实现这两种模式. 在开始介绍模式之前,先解释下wait().notify()和no

详细分析c# 客户端内存优化

背景概述 C# 开发客户端系统的时候,.net 框架本身就比较消耗内存资源,特别是xp 这种老爷机内存配置不是很高的电脑上运行,所以就需要进行内存上的优化,才能流畅的在哪些低端电脑上运行. 想要对C# 开发的客户端内存优化需要了解以下几个概念. 虚拟内存 这里引用百度百科的概念:虚拟内存是计算机系统内存管理的一种技术.它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换.目前,大多

Java超详细分析垃圾回收机制

目录 前言 垃圾回收概述 内存溢出和内存泄漏 垃圾回收算法 标记阶段 STW(Stop-the-World) 回收阶段 标记-清除算法 复制算法 标记-压缩算法 三种算法的比较 总结 前言 在前面我们对类加载, 运行时数据区 ,执行引擎等作了详细的介绍 , 这节我们来看另一重点 : 垃圾回收. 垃圾回收概述 垃圾回收是java的招牌能力 ,极大的提高了开发效率, java是自动化的垃圾回收, 其他语言有的则需要程序员手动回收 , 那么什么是垃圾呢? 垃圾是指在运行程序中没有任何引用指向的对象,这