網站首頁 編程語言 正文
一、說明
到目前為止介紹的功能共享一對一的關系:即一個進程發送和一個進程接收。鏈接是通過標簽建立的。本節介紹在多個進程中調用相同參數但執行不同操作的函數。對于一個進程,函數可能會發送數據,對于另一個進程,它可能會接收數據。這些功能稱為集體操作。
二、示例和代碼
示例 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!到標準輸出流。
原文鏈接:https://yamagota.blog.csdn.net/article/details/127941993
相關推薦
- 2022-07-16 Electron項目打包
- 2022-09-20 ?C++模板template原理解析_C 語言
- 2022-08-30 C語言深入詳解四大內存函數的使用_C 語言
- 2022-06-17 關于Swagger優化的實戰記錄_實用技巧
- 2022-08-26 C++超集C++/CLI模塊的基本類型_C 語言
- 2022-10-02 react中的useImperativeHandle()和forwardRef()用法_React
- 2022-04-25 C#中使用DevExpress中的ChartControl實現極坐標圖的案例詳解_C#教程
- 2022-11-30 C++之值傳遞&指針傳遞&引用傳遞的示例詳解_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支