DARMA » Introduction » Group Manager

Create a grouping of nodes

The group manager component vt::group::GroupManager, accessed via vt::theGroup() manages both rooted and collective groups (or subsets) of nodes that can be broadcast to or reduced over. The group manager implements a fully distributed algorithm for constructing groups collectively with each node deciding if it should be included. The group manager builds a reasonably balanced distributed spanning tree based on these collective votes.

One major use case for the group manager is creating spanning trees for reductions over virtual collections that do not span all the nodes.

When creating a group, one may ask vt to create a underlying MPI group, which can be accessed once the group has finished construction.

Example creating a collective group

struct HelloGroupMsg : vt::Message { };

static void hello_group_handler(HelloGroupMsg* msg) {
  fmt::print("{}: Hello from group handler\n", vt::theContext()->getNode());
}

using ReduceMsg = vt::collective::ReduceTMsg<int>;

struct Print {
  void operator()(ReduceMsg* msg) {
    fmt::print("final value={}\n", msg->getConstVal());
  }
};

int main(int argc, char** argv) {
  vt::initialize(argc, argv);

  vt::NodeType this_node = vt::theContext()->getNode();
  vt::NodeType num_nodes = vt::theContext()->getNumNodes();

  if (num_nodes < 2) {
    return vt::rerror("requires at least 2 nodes");
  }

  srand48(this_node * 29);

  bool odd_node_filter = this_node % 2 == 1;

  vt::GroupType new_group = vt::theGroup()->newGroupCollective(
    odd_node_filter, [=](vt::GroupType group){
      auto const& root = 0;
      auto const& in_group = vt::theGroup()->inGroup(group);
      auto const& root_node = vt::theGroup()->groupRoot(group);
      auto const& is_default_group = vt::theGroup()->isGroupDefault(group);
      fmt::print(
        "{}: Group is created: group={:x}, in_group={}, root={}, "
        "is_default_group={}\n",
        this_node, group, in_group, root_node, is_default_group
      );
      if (in_group) {
        using Op = vt::collective::PlusOp<int>;
        auto msg = vt::makeMessage<ReduceMsg>(1);
        vt::theGroup()->groupReducer(group)->reduce<Op, Print>(root, msg.get());
      }
      if (this_node == 1) {
        auto msg = vt::makeMessage<HelloGroupMsg>();
        vt::envelopeSetGroup(msg->env, group);
        vt::theMsg()->broadcastMsg<hello_group_handler>(msg);
      }
    }
  );

  fmt::print("{}: New group={}\n", this_node, new_group);

  vt::finalize();

  return 0;
}