经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C++异步数据交换实现方法介绍
来源:jb51  时间:2022/11/23 18:50:18  对本文有异议

异步数据交换,除了阻塞函数 send() 和 recv() 之外,Boost.MPI 还支持与成员函数 isend() 和 irecv() 的异步数据交换。名称以 i 开头,表示函数立即返回。

示例 47.7。使用 irecv() 异步接收数据

  1. #include <boost/mpi.hpp>
  2. #include <boost/serialization/string.hpp>
  3. #include <string>
  4. #include <iostream>
  5. int main(int argc, char *argv[])
  6. {
  7. boost::mpi::environment env{argc, argv};
  8. boost::mpi::communicator world;
  9. if (world.rank() == 0)
  10. {
  11. std::string s;
  12. boost::mpi::request r = world.irecv(boost::mpi::any_source, 16, s);
  13. if (r.test())
  14. std::cout << s << '\n';
  15. else
  16. r.cancel();
  17. }
  18. else
  19. {
  20. std::string s = "Hello, world!";
  21. world.send(0, 16, s);
  22. }
  23. }

Example47.7

示例 47.7 使用阻塞函数 send() 发送字符串“Hello, world!”但是,数据是通过异步函数 irecv() 接收的。此成员函数需要与 recv() 相同的参数。不同之处在于,当 irecv() 返回时,无法保证在 s 中已收到数据。

irecv() 返回类型为 boost::mpi::request 的对象。您可以调用 test() 来检查是否已收到数据。此成员函数返回一个布尔值。您可以根据需要随时调用 test()。因为 irecv() 是一个异步成员函数,所以第一次调用可能会返回 false,而第二次调用会返回 true。这意味着异步操作在两次调用之间完成。

示例 47.7 仅调用 test() 一次。如果在 s 中接收到数据,则将变量写入标准输出流。如果没有收到数据,则使用 cancel() 取消异步操作。

如果多次运行示例 47.7,有时会出现 Hello, world!显示,有时没有输出。结果取决于是否在调用 test() 之前接收到数据。

示例 47.8。使用 wait_all() 等待多个异步操作

  1. #include <boost/mpi.hpp>
  2. #include <boost/serialization/string.hpp>
  3. #include <string>
  4. #include <iostream>
  5. int main(int argc, char *argv[])
  6. {
  7. boost::mpi::environment env{argc, argv};
  8. boost::mpi::communicator world;
  9. if (world.rank() == 0)
  10. {
  11. boost::mpi::request requests[2];
  12. std::string s[2];
  13. requests[0] = world.irecv(1, 16, s[0]);
  14. requests[1] = world.irecv(2, 16, s[1]);
  15. boost::mpi::wait_all(requests, requests + 2);
  16. std::cout << s[0] << "; " << s[1] << '\n';
  17. }
  18. else if (world.rank() == 1)
  19. {
  20. std::string s = "Hello, world!";
  21. world.send(0, 16, s);
  22. }
  23. else if (world.rank() == 2)
  24. {
  25. std::string s = "Hello, moon!";
  26. world.send(0, 16, s);
  27. }
  28. }

您可以多次调用 boost::mpi::request 上的 test() 来检测异步操作何时完成。但是,您也可以像示例 47.8 中那样调用阻塞函数 boost::mpi::wait_all()。 boost::mpi::wait_all() 是一个阻塞函数,但好处是可以等待多个异步操作完成。 boost::mpi::wait_all() 在它等待的所有异步操作都已完成时返回。

在示例 47.8 中,等级为 1 的进程发送“Hello, world!”以及排名 2 的过程“你好,月亮!”由于接收数据的顺序无关紧要,因此排名为 0 的进程调用 irecv()。由于程序只会在所有异步操作完成并接收到所有数据时生成输出,因此类型 boost::mpi::request 的返回值被传递给 boost::mpi::wait_all()。因为 boost::mpi::wait_all() 需要两个迭代器,所以 boost::mpi::request 类型的对象存储在一个数组中。开始和结束迭代器被传递给 boost::mpi::wait_all()

Boost.MPI 提供了额外的函数,您可以使用它们来等待异步操作的完成。 boost::mpi::wait_any() 在恰好一个异步操作完成时返回,boost::mpi::wait_some() 在至少一个异步操作完成时返回。这两个函数都返回一个 std::pair 指示哪个或哪些操作已完成。

boost::mpi::test_all()、boost::mpi::test_any() 和 boost::mpi::test_some() 通过一次调用测试多个异步操作的状态。这些函数是非阻塞的并立即返回。

到此这篇关于C++异步数据交换实现方法介绍的文章就介绍到这了,更多相关C++异步数据交换内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号