C++集体数据交换实现示例讲解

目录
  • 一、说明
  • 二、示例和代码

一、说明

到目前为止介绍的功能共享一对一的关系:即一个进程发送和一个进程接收。链接是通过标签建立的。本节介绍在多个进程中调用相同参数但执行不同操作的函数。对于一个进程,函数可能会发送数据,对于另一个进程,它可能会接收数据。这些功能称为集体操作。

二、示例和代码

示例 47.9。使用 gather() 从多个进程接收数据

#include <boost/mpi.hpp>
#include <boost/serialization/string.hpp>
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include <iostream>
int main(int argc, char *argv[])
{
  boost::mpi::environment env{argc, argv};
  boost::mpi::communicator world;
  if (world.rank() == 0)
  {
    std::vector<std::string> v;
    boost::mpi::gather<std::string>(world, "", v, 0);
    std::ostream_iterator<std::string> out{std::cout, "\n"};
    std::copy(v.begin(), v.end(), out);
  }
  else if (world.rank() == 1)
  {
    boost::mpi::gather(world, std::string{"Hello, world!"}, 0);
  }
  else if (world.rank() == 2)
  {
    boost::mpi::gather(world, std::string{"Hello, moon!"}, 0);
  }
}

Example47.9

示例 47.9 在多个进程中调用函数 boost::mpi::gather()。函数是发送还是接收取决于参数。

等级为 1 和 2 的进程使用 boost::mpi::gather() 发送数据。它们将发送的数据作为参数传递——字符串“Hello, world!”和“你好,月亮!” – 以及数据应传输到的进程的级别。由于 boost::mpi::gather() 不是成员函数,因此还必须传递 communicator world。

等级为 0 的进程调用 boost::mpi::gather() 来接收数据。由于数据必须存储在某个地方,因此传递了一个 std::vector<std::string> 类型的对象。请注意,您必须将此类型与 boost::mpi::gather() 一起使用。不支持其他容器或字符串类型。

排名 0 的进程必须传递与排名 1 和 2 的进程相同的参数。这就是排名 0 的进程也传递 world、要发送的字符串和 0 到 boost::mpi::gather() 的原因。

如果您使用三个进程启动示例 47.9,您好,世界!和你好,月亮!被显示。如果仔细查看输出,您会注意到首先写入了一个空行。第一行是等级为 0 的进程传递给 boost::mpi::gather() 的空字符串。 v 中有三个字符串,它们是从等级为 0、1 和 2 的进程接收的。向量中元素的索引对应于进程的等级。如果多次运行该示例,您将始终得到一个空字符串作为向量中的第一个元素,“Hello, world!”作为第二个元素和“你好,月亮!”作为第三个。

请注意,您不得使用超过三个进程运行示例 47.9。例如,如果您使用 -n 4 启动 mpiexec,则不会显示任何数据。该程序将挂起,必须使用 CTRL+C 中止。

必须对所有进程执行集体操作。如果您的程序调用诸如 boost::mpi::gather() 之类的函数,您必须确保该函数在所有进程中都被调用。否则就违反了 MPI 标准。因为像 boost::mpi::gather() 这样的函数必须被所有进程调用,所以每个进程的调用通常没有不同,如示例 47.9 所示。将前面的示例与执行相同操作的示例 47.10 进行比较。

示例 47.10。使用 gather() 从所有进程收集数据

#include <boost/mpi.hpp>
#include <boost/serialization/string.hpp>
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include <iostream>
int main(int argc, char *argv[])
{
  boost::mpi::environment env{argc, argv};
  boost::mpi::communicator world;
  std::string s;
  if (world.rank() == 1)
    s = "Hello, world!";
  else if (world.rank() == 2)
    s = "Hello, moon!";
  std::vector<std::string> v;
  boost::mpi::gather(world, s, v, 0);
  std::ostream_iterator<std::string> out{std::cout, "\n"};
  std::copy(v.begin(), v.end(), out);
}

您为所有流程中的集体操作调用函数。通常函数的定义方式很清楚必须执行哪个操作,即使所有进程都传递相同的参数。

示例 47.10 使用 boost::mpi::gather() 来收集数据。数据在其等级作为最后一个参数传递给 boost::mpi::gather() 的过程中收集。此进程收集它从所有进程接收的数据。存储数据的向量仅供收集数据的进程使用。

boost::mpi::gather() 从所有进程收集数据。这包括收集数据的过程。在示例 47.10 中,这是等级为 0 的进程。该进程在 s 中向自身发送一个空字符串。空字符串存储在 v 中。正如您将在以下示例中看到的,集合操作始终包括所有进程。

您可以使用任意数量的进程运行示例 47.10,因为每个进程都会调用 boost::mpi::gather()。如果您使用三个进程运行该示例,结果将与前面的示例类似。

示例 47.11。在所有进程中使用 scatter() 分散数据

#include <boost/mpi.hpp>
#include <boost/serialization/string.hpp>
#include <vector>
#include <string>
#include <iostream>
int main(int argc, char *argv[])
{
  boost::mpi::environment env{argc, argv};
  boost::mpi::communicator world;
  std::vector<std::string> v{"Hello, world!", "Hello, moon!",
    "Hello, sun!"};
  std::string s;
  boost::mpi::scatter(world, v, s, 0);
  std::cout << world.rank() << ": " << s << '\n';
}

Example47.11

示例 47.11 介绍了函数 boost::mpi::scatter()。它与 boost::mpi::gather() 相反。 boost::mpi::gather() 将来自多个进程的数据收集到一个进程中,而 boost::mpi::scatter() 将来自一个进程的数据分散到多个进程中。

示例 47.11 将来自排名为 0 的进程的 v 中的数据分散到所有进程,包括它自己。等级为 0 的进程接收到字符串“Hello, world!”在 s 中,排名为 1 的进程收到“你好,月亮!”在 s 中,等级为 2 的进程收到“Hello, sun!”秒。

示例 47.12。使用 broadcast() 向所有进程发送数据

#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;
  std::string s;
  if (world.rank() == 0)
    s = "Hello, world!";
  boost::mpi::broadcast(world, s, 0);
  std::cout << s << '\n';
}

boost::mpi::broadcast() 将数据从一个进程发送到所有进程。此函数与 boost::mpi::scatter() 之间的区别在于将相同的数据发送到所有进程。在示例 47.12 中,所有进程都收到字符串“Hello, world!”在 s 中写下你好,世界!到标准输出流。

示例 47.13。使用 reduce() 收集和分析数据

#include <boost/mpi.hpp>
#include <boost/serialization/string.hpp>
#include <string>
#include <iostream>
std::string min(const std::string &lhs, const std::string &rhs)
{
  return lhs.size() < rhs.size() ? lhs : rhs;
}
int main(int argc, char *argv[])
{
  boost::mpi::environment env{argc, argv};
  boost::mpi::communicator world;
  std::string s;
  if (world.rank() == 0)
    s = "Hello, world!";
  else if (world.rank() == 1)
    s = "Hello, moon!";
  else if (world.rank() == 2)
    s = "Hello, sun!";
  std::string result;
  boost::mpi::reduce(world, s, result, min, 0);
  if (world.rank() == 0)
    std::cout << result << '\n';
}

boost::mpi::reduce() 从多个进程收集数据,如 boost::mpi::gather()。但是,数据不存储在向量中。 boost::mpi::reduce() 需要一个函数或函数对象,它将用于分析数据。

如果您使用三个进程运行示例 47.13,则排名为 0 的进程会收到字符串“Hello, sun!”结果。对 boost::mpi::reduce() 的调用收集并分析所有进程传递给它的字符串。它们使用函数 min() 进行分析,该函数作为第四个参数传递给 boost::mpi::reduce()。 min() 比较两个字符串并返回较短的一个。

如果您使用三个以上的进程运行示例 47.13,则会显示一个空字符串,因为排名大于 2 的所有进程都会将一个空字符串传递给 boost::mpi::reduce()。将显示空字符串,因为它比“Hello, sun!”短

示例 47.14。使用 all_reduce() 收集和分析数据

#include <boost/mpi.hpp>
#include <boost/serialization/string.hpp>
#include <string>
#include <iostream>
std::string min(const std::string &lhs, const std::string &rhs)
{
  return lhs.size() < rhs.size() ? lhs : rhs;
}
int main(int argc, char *argv[])
{
  boost::mpi::environment env{argc, argv};
  boost::mpi::communicator world;
  std::string s;
  if (world.rank() == 0)
    s = "Hello, world!";
  else if (world.rank() == 1)
    s = "Hello, moon!";
  else if (world.rank() == 2)
    s = "Hello, sun!";
  std::string result;
  boost::mpi::all_reduce(world, s, result, min);
  std::cout << world.rank() << ": " << result << '\n';
}

Example47.14

示例 47.14 使用函数 boost::mpi::all_reduce(),它像 boost::mpi::reduce() 一样收集和分析数据。这两个函数之间的区别在于 boost::mpi::all_reduce() 将分析结果发送到所有进程,而 boost::mpi::reduce() 使结果仅可用于排名作为传递的进程最后一个参数。因此,没有排名传递给 boost::mpi::all_reduce()。如果您使用三个进程运行示例 47.14,每个进程都会写入 Hello, sun!到标准输出流。

到此这篇关于C++集体数据交换实现示例讲解的文章就介绍到这了,更多相关C++集体数据交换内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++中4种管理数据内存的方式总结

    目录 C++的4种管理数据内存的方式 自动存储 静态存储 动态存储 线程存储 栈.堆.内存泄漏 根据用于分配内存的方法,C++中有3中管理数据内存的方式:自动存储.静态存储和动态存储(有时也叫做自由存储空间或堆).在存在时间的长短方面,以这三种方式分配的数据对象各不相同.下面简要介绍这三种类型. 注:C++11中新增了第四种类型——线程存储 C++的4种管理数据内存的方式 自动存储 在函数内部定义的常规变量使用自动存储空间,被称为自动变量(automatic variable),这意味着它们在所

  • C++浅析数据在内存中如何存储

    目录 一.数据类型 二.原码反码补码 三.大小端 整型提升 一.数据类型 数据类型有7种: char            字符型     short          短整型    int               整型   long            长整型   long long    更长整型   float            单精度浮点数    double        双精度浮点数 二.原码反码补码 计算机中的整数有三种2进制表示方法,即原码.反码和补码. 三种表示方法均

  • C++数据结构之二叉搜索树的实现详解

    目录 前言 介绍 实现 节点的实现 二叉搜索树的查找 二叉搜索树的插入 二叉搜索树的删除 总结 前言 今天我们来学一个新的数据结构:二叉搜索树. 介绍 二叉搜索树也称作二叉排序树,它具有以下性质: 非空左子树的所有键值小于其根节点的键值 非空右子树的所有键值大于其根节点的键值 左,右子树都是二叉搜索树 那么我先画一个二叉搜索树给大家看看,是不是真的满足上面的性质. 我们就以根节点6为例子来看,我们会发现比6小的都在6的左边,而比6大的都在6的右边.对于6的左右子树来说,所有的节点都遵循这个规则.

  • C++集体数据交换实现示例讲解

    目录 一.说明 二.示例和代码 一.说明 到目前为止介绍的功能共享一对一的关系:即一个进程发送和一个进程接收.链接是通过标签建立的.本节介绍在多个进程中调用相同参数但执行不同操作的函数.对于一个进程,函数可能会发送数据,对于另一个进程,它可能会接收数据.这些功能称为集体操作. 二.示例和代码 示例 47.9.使用 gather() 从多个进程接收数据 #include <boost/mpi.hpp> #include <boost/serialization/string.hpp>

  • thymeleaf实现前后端数据交换的示例详解

    目录 1.前端传数据后端接收: 2.后端对数据判断后返回信息给前端: Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎.它与 JSP,Velocity,FreeMaker 等模板引擎类似,也可以轻易地与 Spring MVC 等 Web 框架集成.与其它模板引擎相比,Thymeleaf 最大的特点是,即使不启动 Web 应用,也可以直接在浏览器中打开并正确显示模板页面 . 1.前端传数据后端接收: 用户在登录界面输入用户名和密码传给后端controller,由后

  • Laravel基础_关于view共享数据的示例讲解

    1.所有视图共享数据(share) 当所有视图都需要同一个数据时,使用视图工厂的share方法. 全局帮助函数view,如果传入参数,则返回Illuminate\View\View实例,不传入参数则返回Illuminate\View\Factory实例.所以我们可以通过在服务提供者(app\Providers\AppServiceProvider.php)的boot方法中使用如下方式实现视图间共享数据: /** * Bootstrap any application services. * *

  • selenium + python 获取table数据的示例讲解

    方法一: <code class="language-python">""" 根据table的id属性和table中的某一个元素定位其在table中的位置 table包括表头,位置坐标都是从1开始算 tableId:table的id属性 queryContent:需要确定位置的内容 """ def get_table_content(tableId,queryContent): arr = [] arr1 = []

  • python实战之实现excel读取、统计、写入的示例讲解

    背景 图像领域内的一个国内会议快要召开了,要发各种邀请邮件,之后要录入.统计邮件回复(参会还是不参会等).如此重要的任务,老师就托付给我了.ps: 统计回复邮件的时候,能知道谁参会或谁不参会. 而我主要的任务,除了录入邮件回复,就是统计理事和普通会员的参会情况了(参会的.不参会的.没回复的).录入邮件回复信息没办法只能人工操作,但如果统计也要人工的话,那工作量就太大了(比如在上百人的列表中搜索另外上百人在不在此列表中!!),于是就想到了用python来帮忙,花两天时间不断修改,写了6个版本...

  • C++ 超详细示例讲解list的使用

    目录 一.list的介绍 list的介绍 二.list的使用 2.1 list的构造函数 2.2 list迭代器的使用 2.3 list相关的容量大小相关的函数 2.4 list数据的访问相关的函数 2.5 list的数据调整相关的函数 2.6 list中其他函数操作 一.list的介绍 list的介绍 list是可以以O(1)的时间复杂度任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针

  • PHP中使用jQuery+Ajax实现分页查询多功能操作(示例讲解)

    1.首先做主页面Ajax_pag.php 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Ajax做分页</title> <script src="bootstrap/js/jquery-1.11.2.min.js"></script> <script src="Ajax_

  • 用Json实现PHP与JavaScript间数据交换的方法详解

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.简而论之,不管是xml还是json都是为了方便在客户端与服务器端交互数据的中转站,特别是用于对象型数据,比如最常见的数组. 下面将分别将数组从php传送给javascript,以及将数组从javascript传送给php示例说明,例子比较简单,明白概念即可.不管从php传送给javascript,还是javascript传送给php,json在传送之前都会将对象扁平化即一维化为字符串.PHP 向 Jav

  • 在.NET使用JSON作为数据交换格式实例演示

    我们知道在NET中我们有多种对象序列化的方式,如XML方式序列化.Binary序列化,其中XML序列化是一种比较通用的在各语言之间传递数据的方式.除了这两种序列化方式之外,在NET中还可以使用JSON序列化. JSON(JavaScript Object Notation)是一种轻量级轻量级的数据交换格式,并且它独立于编程语言,与XML序列化相比,JSON序列化后产生的数据一般要比XML序列化后数据体积小,所以在Facebook等知名网站中都采用了JSON作为数据交换方式.在NET中有三种常用的

  • WPF MVVM示例讲解

    在没给大家讲解wpf mwm示例之前先给大家简单说下MVVM理论知识: WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的,WPF提供了数据绑定机制,当数据发生变化时,WPF会自动发出通知去更新UI. 我们使用模式,一般是想达到高内聚低耦合.在WPF开发中,经典的编程模式是MVVM,是为WPF量身定做的模式,该模式充分利用了WPF的数据绑定机制,最大限度地降低了Xmal文件和CS文件的耦合度,也就是UI显示和逻辑代码的耦合度,如需要更换界面时,逻辑代码修改很少,

随机推荐