C++集體數(shù)據(jù)交換實(shí)現(xiàn)示例講解
一、說(shuō)明
到目前為止介紹的功能共享一對(duì)一的關(guān)系:即一個(gè)進(jìn)程發(fā)送和一個(gè)進(jìn)程接收。鏈接是通過(guò)標(biāo)簽建立的。本節(jié)介紹在多個(gè)進(jìn)程中調(diào)用相同參數(shù)但執(zhí)行不同操作的函數(shù)。對(duì)于一個(gè)進(jìn)程,函數(shù)可能會(huì)發(fā)送數(shù)據(jù),對(duì)于另一個(gè)進(jìn)程,它可能會(huì)接收數(shù)據(jù)。這些功能稱為集體操作。
二、示例和代碼
示例 47.9。使用 gather() 從多個(gè)進(jìn)程接收數(shù)據(jù)
#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); } }
示例 47.9 在多個(gè)進(jìn)程中調(diào)用函數(shù) boost::mpi::gather()。函數(shù)是發(fā)送還是接收取決于參數(shù)。
等級(jí)為 1 和 2 的進(jìn)程使用 boost::mpi::gather() 發(fā)送數(shù)據(jù)。它們將發(fā)送的數(shù)據(jù)作為參數(shù)傳遞——字符串“Hello, world!”和“你好,月亮!” – 以及數(shù)據(jù)應(yīng)傳輸?shù)降倪M(jìn)程的級(jí)別。由于 boost::mpi::gather() 不是成員函數(shù),因此還必須傳遞 communicator world。
等級(jí)為 0 的進(jìn)程調(diào)用 boost::mpi::gather() 來(lái)接收數(shù)據(jù)。由于數(shù)據(jù)必須存儲(chǔ)在某個(gè)地方,因此傳遞了一個(gè) std::vector<std::string> 類型的對(duì)象。請(qǐng)注意,您必須將此類型與 boost::mpi::gather() 一起使用。不支持其他容器或字符串類型。
排名 0 的進(jìn)程必須傳遞與排名 1 和 2 的進(jìn)程相同的參數(shù)。這就是排名 0 的進(jìn)程也傳遞 world、要發(fā)送的字符串和 0 到 boost::mpi::gather() 的原因。
如果您使用三個(gè)進(jìn)程啟動(dòng)示例 47.9,您好,世界!和你好,月亮!被顯示。如果仔細(xì)查看輸出,您會(huì)注意到首先寫(xiě)入了一個(gè)空行。第一行是等級(jí)為 0 的進(jìn)程傳遞給 boost::mpi::gather() 的空字符串。 v 中有三個(gè)字符串,它們是從等級(jí)為 0、1 和 2 的進(jìn)程接收的。向量中元素的索引對(duì)應(yīng)于進(jìn)程的等級(jí)。如果多次運(yùn)行該示例,您將始終得到一個(gè)空字符串作為向量中的第一個(gè)元素,“Hello, world!”作為第二個(gè)元素和“你好,月亮!”作為第三個(gè)。
請(qǐng)注意,您不得使用超過(guò)三個(gè)進(jìn)程運(yùn)行示例 47.9。例如,如果您使用 -n 4 啟動(dòng) mpiexec,則不會(huì)顯示任何數(shù)據(jù)。該程序?qū)炱?,必須使?CTRL+C 中止。
必須對(duì)所有進(jìn)程執(zhí)行集體操作。如果您的程序調(diào)用諸如 boost::mpi::gather() 之類的函數(shù),您必須確保該函數(shù)在所有進(jìn)程中都被調(diào)用。否則就違反了 MPI 標(biāo)準(zhǔn)。因?yàn)橄?boost::mpi::gather() 這樣的函數(shù)必須被所有進(jìn)程調(diào)用,所以每個(gè)進(jìn)程的調(diào)用通常沒(méi)有不同,如示例 47.9 所示。將前面的示例與執(zhí)行相同操作的示例 47.10 進(jìn)行比較。
示例 47.10。使用 gather() 從所有進(jìn)程收集數(shù)據(jù)
#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); }
您為所有流程中的集體操作調(diào)用函數(shù)。通常函數(shù)的定義方式很清楚必須執(zhí)行哪個(gè)操作,即使所有進(jìn)程都傳遞相同的參數(shù)。
示例 47.10 使用 boost::mpi::gather() 來(lái)收集數(shù)據(jù)。數(shù)據(jù)在其等級(jí)作為最后一個(gè)參數(shù)傳遞給 boost::mpi::gather() 的過(guò)程中收集。此進(jìn)程收集它從所有進(jìn)程接收的數(shù)據(jù)。存儲(chǔ)數(shù)據(jù)的向量?jī)H供收集數(shù)據(jù)的進(jìn)程使用。
boost::mpi::gather() 從所有進(jìn)程收集數(shù)據(jù)。這包括收集數(shù)據(jù)的過(guò)程。在示例 47.10 中,這是等級(jí)為 0 的進(jìn)程。該進(jìn)程在 s 中向自身發(fā)送一個(gè)空字符串??兆址鎯?chǔ)在 v 中。正如您將在以下示例中看到的,集合操作始終包括所有進(jìn)程。
您可以使用任意數(shù)量的進(jìn)程運(yùn)行示例 47.10,因?yàn)槊總€(gè)進(jìn)程都會(huì)調(diào)用 boost::mpi::gather()。如果您使用三個(gè)進(jìn)程運(yùn)行該示例,結(jié)果將與前面的示例類似。
示例 47.11。在所有進(jìn)程中使用 scatter() 分散數(shù)據(jù)
#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'; }
示例 47.11 介紹了函數(shù) boost::mpi::scatter()。它與 boost::mpi::gather() 相反。 boost::mpi::gather() 將來(lái)自多個(gè)進(jìn)程的數(shù)據(jù)收集到一個(gè)進(jìn)程中,而 boost::mpi::scatter() 將來(lái)自一個(gè)進(jìn)程的數(shù)據(jù)分散到多個(gè)進(jìn)程中。
示例 47.11 將來(lái)自排名為 0 的進(jìn)程的 v 中的數(shù)據(jù)分散到所有進(jìn)程,包括它自己。等級(jí)為 0 的進(jìn)程接收到字符串“Hello, world!”在 s 中,排名為 1 的進(jìn)程收到“你好,月亮!”在 s 中,等級(jí)為 2 的進(jìn)程收到“Hello, sun!”秒。
示例 47.12。使用 broadcast() 向所有進(jìn)程發(fā)送數(shù)據(jù)
#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() 將數(shù)據(jù)從一個(gè)進(jìn)程發(fā)送到所有進(jìn)程。此函數(shù)與 boost::mpi::scatter() 之間的區(qū)別在于將相同的數(shù)據(jù)發(fā)送到所有進(jìn)程。在示例 47.12 中,所有進(jìn)程都收到字符串“Hello, world!”在 s 中寫(xiě)下你好,世界!到標(biāo)準(zhǔn)輸出流。
示例 47.13。使用 reduce() 收集和分析數(shù)據(jù)
#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() 從多個(gè)進(jìn)程收集數(shù)據(jù),如 boost::mpi::gather()。但是,數(shù)據(jù)不存儲(chǔ)在向量中。 boost::mpi::reduce() 需要一個(gè)函數(shù)或函數(shù)對(duì)象,它將用于分析數(shù)據(jù)。
如果您使用三個(gè)進(jìn)程運(yùn)行示例 47.13,則排名為 0 的進(jìn)程會(huì)收到字符串“Hello, sun!”結(jié)果。對(duì) boost::mpi::reduce() 的調(diào)用收集并分析所有進(jìn)程傳遞給它的字符串。它們使用函數(shù) min() 進(jìn)行分析,該函數(shù)作為第四個(gè)參數(shù)傳遞給 boost::mpi::reduce()。 min() 比較兩個(gè)字符串并返回較短的一個(gè)。
如果您使用三個(gè)以上的進(jìn)程運(yùn)行示例 47.13,則會(huì)顯示一個(gè)空字符串,因?yàn)榕琶笥?2 的所有進(jìn)程都會(huì)將一個(gè)空字符串傳遞給 boost::mpi::reduce()。將顯示空字符串,因?yàn)樗?ldquo;Hello, sun!”短
示例 47.14。使用 all_reduce() 收集和分析數(shù)據(jù)
#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'; }
示例 47.14 使用函數(shù) boost::mpi::all_reduce(),它像 boost::mpi::reduce() 一樣收集和分析數(shù)據(jù)。這兩個(gè)函數(shù)之間的區(qū)別在于 boost::mpi::all_reduce() 將分析結(jié)果發(fā)送到所有進(jìn)程,而 boost::mpi::reduce() 使結(jié)果僅可用于排名作為傳遞的進(jìn)程最后一個(gè)參數(shù)。因此,沒(méi)有排名傳遞給 boost::mpi::all_reduce()。如果您使用三個(gè)進(jìn)程運(yùn)行示例 47.14,每個(gè)進(jìn)程都會(huì)寫(xiě)入 Hello, sun!到標(biāo)準(zhǔn)輸出流。
到此這篇關(guān)于C++集體數(shù)據(jù)交換實(shí)現(xiàn)示例講解的文章就介紹到這了,更多相關(guān)C++集體數(shù)據(jù)交換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解c/c++鏈?zhǔn)蕉褩C枋鲞M(jìn)制轉(zhuǎn)換問(wèn)題示例
這篇文章主要為大家介紹了c/c++鏈?zhǔn)蕉褩C枋鲞M(jìn)制轉(zhuǎn)換問(wèn)題示例解析有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11C++實(shí)現(xiàn)簡(jiǎn)單的學(xué)生管理系統(tǒng)
本文給大家分享的是使用C++實(shí)現(xiàn)的簡(jiǎn)單的學(xué)生管理系統(tǒng)的代碼,主要是通過(guò)鏈表來(lái)實(shí)現(xiàn),非常簡(jiǎn)潔,有需要的小伙伴可以參考下。2015-07-07window調(diào)用api列出當(dāng)前所有進(jìn)程示例
這篇文章主要介紹了window調(diào)用api列出當(dāng)前所有進(jìn)程示例,需要的朋友可以參考下2014-04-04static全局變量與普通的全局變量的區(qū)別詳細(xì)解析
以下是對(duì)static全局變量與普通的全局變量的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-09-09