首頁 > 軟體

C++程序連結工具之通訊器詳解

2022-11-21 14:01:00

一、傳播者

本章中的所有範例僅使用一個連線所有程序的通訊器。但是,可以建立更多的通訊器來連結程序的子集。這對於不需要由所有程序執行的集體操作特別有用。

二、範例和程式碼

範例 47.15。使用多個通訊器

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

Example47.15

範例 47.15 使用函數 boost::mpi::broadcast()。此函數傳送字串“Hello, world!”從等級為 0 的程序到連結到本地​​通訊器的所有程序。等級為 0 的程序也必須連結到該通訊器。

本地通訊器是通過呼叫 split() 建立的。 split() 是在全域性通訊器世界上呼叫的成員函數。 split() 需要一個整數來將程序連結在一起。將相同整數傳遞給 split() 的所有程序都連結到相同的通訊器。傳遞給 split() 的整數值無關緊要。重要的是應該由特定通訊器連結的所有程序都傳遞相同的值。

在範例 47.15 中,等級為 0 和 1 的兩個程序將 99 傳遞給 split()。如果程式啟動時有兩個以上的程序,則額外的程序會傳遞 100。這意味著前兩個程序有一個本地通訊器,所有其他程序都有另一個本地通訊器。每個程序都連結到 split() 返回的通訊器。是否有其他程序連結到同一個通訊器取決於其他程序是否將相同的整數傳遞給 split()。

請注意,等級始終與傳播者有關。最低等級始終為 0。在範例 47.15 中,相對於全域性通訊器具有等級 0 的程序相對於其本地通訊器也具有等級 0。相對於全域性通訊器具有等級 2 的程序相對於其本地通訊器具有等級 0。

如果您使用兩個或更多程序啟動範例 47.15,您好,世界!將顯示兩次 - 每次由相對於全域性通訊器的等級為 0 和 1 的程序顯示一次。因為 s 設定為“Hello, world!”僅在全域性等級為 0 的程序中,此字串僅通過通訊器傳送到連結到同一通訊器的那些程序。這只是具有全域性排名 1 的程序,這是唯一將 99 傳遞給 split() 的其他程序。

範例 47.16。使用組對流程進行分組

#include <boost/mpi.hpp>
#include <boost/serialization/string.hpp>
#include <boost/range/irange.hpp>
#include <boost/optional.hpp>
#include <string>
#include <iostream>
int main(int argc, char *argv[])
{
  boost::mpi::environment env{argc, argv};
  boost::mpi::communicator world;
  boost::mpi::group local = world.group();
  boost::integer_range<int> r = boost::irange(0, 1);
  boost::mpi::group subgroup = local.exclude(r.begin(), r.end());
  boost::mpi::communicator others{world, subgroup};
  std::string s;
  boost::optional<int> rank = subgroup.rank();
  if (rank)
  {
    if (rank == 0)
      s = "Hello, world!";
    boost::mpi::broadcast(others, s, 0);
  }
  std::cout << world.rank() << ": " << s << 'n';
}

MPI 支援分組程序。這是在類 boost::mpi::group 的幫助下完成的。如果您在通訊器上呼叫成員函數 group(),則連結到通訊器的所有程序都將在型別為 boost::mpi::group 的物件中返回。您不能使用此物件進行通訊。它只能用於形成一組新的程序,然後可以從中建立通訊器。

boost::mpi::group 提供成員函數,如 include() 和 exclude()。您傳遞迭代器以包含或排除程序。 include() 和 exclude() 返回一個型別為 boost::mpi::group 的新組。

範例 47.16 將兩個迭代器傳遞給 exclude(),它們參照型別為 boost::integer_range 的物件。該物件表示一個整數範圍。它是在函數 boost::irange() 的幫助下建立的,它需要一個下限和上限。上限是一個不屬於該範圍的整數。在此範例中,這意味著 r 僅包含整數 0。

呼叫 exclude() 會導致建立子組,其中包含除等級為 0 的程序之外的所有程序。然後使用該組建立一個新的通訊器 others。這是通過將全域性通訊器世界和子組傳遞給 boost::mpi::communicator 的建構函式來完成的。

請注意,others 是一個 communicator,它在 rank 0 的程序中是空的。rank 0 的程序沒有連結到這個 communicator,但是變數 others 仍然存在於這個程序中。您必須注意不要在此過程中使用其他人。範例 47.16 通過在子組上呼叫 rank() 來防止這種情況。成員函數在不屬於該組的程序中返回一個型別為 boost::optional 的空物件。其他程序接收它們相對於該組的等級。

如果 rank() 返回排名並且沒有型別為 boost::optional 的空物件,則呼叫 boost::mpi::broadcast()。等級為 0 的程序傳送字串“Hello, world!”連結到其他通訊器的所有程序。請注意,等級是相對於那個傳播者的。相對於其他程序排名為 0 的程序相對於全球通訊者世界排名為 1。

如果您使用兩個以上的程序執行範例 47.16,則全域性等級大於 0 的所有程序都將顯示 Hello, world!。

到此這篇關於C++程序連結工具之通訊器詳解的文章就介紹到這了,更多相關C++通訊器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com