C++异步数据交换实现方法介绍
无水先生 人气:0异步数据交换,除了阻塞函数 send() 和 recv() 之外,Boost.MPI 还支持与成员函数 isend() 和 irecv() 的异步数据交换。名称以 i 开头,表示函数立即返回。
示例 47.7。使用 irecv() 异步接收数据
#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; if (world.rank() == 0) { std::string s; boost::mpi::request r = world.irecv(boost::mpi::any_source, 16, s); if (r.test()) std::cout << s << '\n'; else r.cancel(); } else { std::string s = "Hello, world!"; world.send(0, 16, s); } }
示例 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() 等待多个异步操作
#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; if (world.rank() == 0) { boost::mpi::request requests[2]; std::string s[2]; requests[0] = world.irecv(1, 16, s[0]); requests[1] = world.irecv(2, 16, s[1]); boost::mpi::wait_all(requests, requests + 2); std::cout << s[0] << "; " << s[1] << '\n'; } else if (world.rank() == 1) { std::string s = "Hello, world!"; world.send(0, 16, s); } else if (world.rank() == 2) { std::string s = "Hello, moon!"; world.send(0, 16, s); } }
您可以多次调用 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() 通过一次调用测试多个异步操作的状态。这些函数是非阻塞的并立即返回。
加载全部内容