{"id":697,"date":"2015-09-01T21:50:52","date_gmt":"2015-09-01T20:50:52","guid":{"rendered":"http:\/\/numbercrunch.de\/blog\/?p=697"},"modified":"2023-01-18T22:01:05","modified_gmt":"2023-01-18T21:01:05","slug":"mpl-collective-communication","status":"publish","type":"post","link":"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/","title":{"rendered":"MPL &#8211; Collective communication"},"content":{"rendered":"<p style=\"text-align: justify;\">In a previous <a href=\"http:\/\/numbercrunch.de\/blog\/2015\/08\/mpl-a-message-passing-library\/\">post<\/a> I gave a very short introduction to the Message Passing Library (MPL), which is a C++ message passing library based on MPI. Although it does not provide a direct mapping of the C API to C++ it comes with all modes of collective communication as defined be the MPI standard, e.g., barrier, broadcast, gather, scatter, reduce and so on. The following program does not perform any meaningful calculation, but illustrates some modes of collective communication.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include &lt;cstdlib&gt;\n#include &lt;complex&gt;\n#include &lt;iostream&gt;\n#include &lt;vector&gt;\n#include &lt;mpl\/mpl.hpp&gt;\n\nint main() {\n  const mpl::communicator &amp;comm_world=mpl::environment::comm_world();\n  std::vector&lt;int&gt; v;\n  if (comm_world.rank()==0)\n    for (int i=0; i&lt;comm_world.size(); ++i)\n      v.push_back(i);\n  int x;\n  \/\/ rank 0 scatters data to all processes\n  comm_world.scatter(0, v.data(), x);\n  std::cout &lt;&lt; \"rank \" &lt;&lt; comm_world.rank() &lt;&lt; \" got \" &lt;&lt; x &lt;&lt; '\\n';\n  \/\/ wait until all processes have reached this point\n  comm_world.barrier();\n  x*=2;\n  \/\/ rank 0 gathers data from all processes\n  comm_world.gather(0, x, v.data());\n  if (comm_world.rank()==0)\n    for (int i=0; i&lt;comm_world.size(); ++i)\n      std::cout &lt;&lt; \"got \" &lt;&lt; v[i] &lt;&lt; \" from rank \" &lt;&lt; i &lt;&lt; '\\n';\n  \/\/ wait until all processes have reached this point\n  comm_world.barrier();\n  \/\/ calculate global sum and pass result to rank 0\n  if (comm_world.rank()==0) {\n    int sum;\n    comm_world.reduce(mpl::plus&lt;int&gt;(), 0, x, sum);\n    std::cout &lt;&lt; \"sum = \" &lt;&lt; sum &lt;&lt; '\\n';\n  } else\n    comm_world.reduce(mpl::plus&lt;int&gt;(), 0, x);\n  \/\/ wait until all processes have reached this point\n  comm_world.barrier();\n  \/\/ calculate global sum and pass result to all\n  comm_world.allreduce(mpl::plus&lt;int&gt;(), x);\n  std::cout &lt;&lt; \"sum = \" &lt;&lt; x &lt;&lt; '\\n';\n  return EXIT_SUCCESS;\n}\n<\/pre>\n<p>Note that the reduction operation (addition) in the example above is specified as an anonymous function object. In addition to addition, MPL provides multiplication, logical operations \u00bband\u00ab and \u00bbor\u00ab, bitwise operations \u00bband\u00ab, \u00bbor\u00ab, and \u00bbxor\u00ab as well as minimum and maximum. A reduction operation must take two arguments of the same kind and produce a result of the same type as the arguments. With MPL it becomes very easy to define custom reduction operations, as the following example shows. Note that it is required, that the reduction operation is implemented by a class, which is derived from <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/utility\/functional\/function\" target=\"_blank\" rel=\"noopener\"><code>std::function<\/code><\/a> and has no member variables.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include &lt;cstdlib&gt;\n#include &lt;ctime&gt;\n#include &lt;iostream&gt;\n#include &lt;functional&gt;\n#include &lt;vector&gt;\n#include &lt;mpl\/mpl.hpp&gt;\n\n\/\/ calculate least common multiple of two arguments \ntemplate&lt;typename T&gt;\nclass lcm : public std::function&lt;T (T, T)&gt; {\n  \/\/ helper: calculate greatest common divisor\n  T gcd(T a, T b) {\n    T zero=T(), t;\n    if (a&lt;zero) a=-a;\n    if (b&lt;zero) b=-b;\n    while (b&gt;zero) {\n      t=a%b;  a=b;  b=t;\n    }\n    return a;\n  }\npublic:\n  T operator()(T a, T b) {\n    T zero=T();\n    T t((a\/gcd(a, b))*b);\n    if (t&lt;zero)\n      return -t;\n    return t;\n  }\n};\n\nint main() {\n  const mpl::communicator &amp;comm_world=mpl::environment::comm_world();\n  \/\/ generate data\n  std::srand(std::time(0)*comm_world.rank());  \/\/ random seed\n  int v=std::rand()%12+1;\n  \/\/ calculate least common multiple and send result to rank 0\n  if (comm_world.rank()==0) {\n    int result;\n    \/\/ calculate least common multiple\n    comm_world.reduce(lcm&lt;int&gt;(), 0, v, result);\n    \/\/ display data from all ranks\n    std::cout &lt;&lt; \"Arguments:\\n\";\n    for (int r=0; r&lt;comm_world.size(); ++r) {\n      if (r&gt;0)\n    comm_world.recv(v, r);\n      std::cout &lt;&lt; v &lt;&lt; '\\n';\n    }\n    \/\/ display results of global reduction\n    std::cout &lt;&lt; \"\\nResult:\\n\";\n    std::cout &lt;&lt; result &lt;&lt; '\\n';\n  } else {\n    \/\/ calculate least common multiple\n    comm_world.reduce(lcm&lt;int&gt;(), 0, v);\n    \/\/ send data to rank 0 for display\n    comm_world.send(v, 0);\n  }\n  return EXIT_SUCCESS;\n}\n<\/pre>\n<p style=\"text-align: justify;\">MPI provides reductions operations MINLOC and MAXLOC, which simultaneously determine the minimum or maximum plus the location of the minimum or maximum. In MPL, however, such specific operations are not needed. Minimum and maximum operations for pairs of some scalar type and an integer do the same job as the following example shows.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include &lt;cstdlib&gt;\n#include &lt;ctime&gt;\n#include &lt;iostream&gt;\n#include &lt;iomanip&gt;\n#include &lt;vector&gt;\n#include &lt;utility&gt;\n#include &lt;mpl\/mpl.hpp&gt;\n\ntypedef std::pair&lt;double, int&gt; pair_t;\n\nint main() {\n  const mpl::communicator &amp;comm_world=mpl::environment::comm_world();\n  \/\/ generate data\n  std::srand(std::time(0)*comm_world.rank());  \/\/ random seed\n  const int n=8;\n  std::vector&lt;pair_t&gt; v(n);\n  for (pair_t &amp;i : v)\n    i=std::make_pair(static_cast&lt;double&gt;(std::rand())\/RAND_MAX, comm_world.rank());\n  \/\/ calculate minium and its location and send result to rank 0\n  mpl::contiguous_layout&lt;pair_t&gt; layout(n);\n  if (comm_world.rank()==0) {\n    std::vector&lt;pair_t&gt; result(n);\n    \/\/ calculate minimum\n    comm_world.reduce(mpl::min&lt;pair_t&gt;(), 0, v.data(), result.data(), layout);\n    \/\/ display data from all ranks\n    std::cout &lt;&lt; \"Arguments:\\n\";\n    for (int r=0; r&lt;comm_world.size(); ++r) {\n      if (r&gt;0)\n    comm_world.recv(v.data(), layout, r);\n      for (pair_t i : v) \n    std::cout &lt;&lt; std::fixed &lt;&lt; std::setprecision(5) &lt;&lt; i.first &lt;&lt; ' ' &lt;&lt; i.second &lt;&lt; '\\t';\n      std::cout &lt;&lt; '\\n';\n    }\n    \/\/ display results of global reduction\n    std::cout &lt;&lt; \"\\nResults:\\n\";\n    for (pair_t i : result) \n      std::cout &lt;&lt; std::fixed &lt;&lt; std::setprecision(5) &lt;&lt; i.first &lt;&lt; ' ' &lt;&lt; i.second &lt;&lt; '\\t';\n    std::cout &lt;&lt; '\\n';\n  } else {\n    \/\/ calculate minium and its location and send result to rank 0\n    comm_world.reduce(mpl::min&lt;pair_t&gt;(), 0, v.data(), layout);\n    \/\/ send data to rank 0 for display\n    comm_world.send(v.data(), layout, 0);\n  }\n  return EXIT_SUCCESS;\n}\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>In a previous post I gave a very short introduction to the Message Passing Library (MPL), which is a C++ message passing library based on MPI. Although it does not provide a direct mapping of the C API to C++ it comes with all modes of collective communication as defined be the MPI standard, e.g.,&hellip; <a href=\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">MPL &#8211; Collective communication<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16,9,8],"tags":[],"class_list":["post-697","post","type-post","status-publish","format-standard","hentry","category-c","category-mpi","category-parallel-computing"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v25.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>MPL - Collective communication - Number Crunch<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"MPL - Collective communication - Number Crunch\" \/>\n<meta property=\"og:description\" content=\"In a previous post I gave a very short introduction to the Message Passing Library (MPL), which is a C++ message passing library based on MPI. Although it does not provide a direct mapping of the C API to C++ it comes with all modes of collective communication as defined be the MPI standard, e.g.,&hellip; Continue reading MPL &#8211; Collective communication\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/\" \/>\n<meta property=\"og:site_name\" content=\"Number Crunch\" \/>\n<meta property=\"article:published_time\" content=\"2015-09-01T20:50:52+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-01-18T21:01:05+00:00\" \/>\n<meta name=\"author\" content=\"Heiko Bauke\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Heiko Bauke\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/\"},\"author\":{\"name\":\"Heiko Bauke\",\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413\"},\"headline\":\"MPL &#8211; Collective communication\",\"datePublished\":\"2015-09-01T20:50:52+00:00\",\"dateModified\":\"2023-01-18T21:01:05+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/\"},\"wordCount\":239,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413\"},\"articleSection\":[\"C++\",\"MPI\",\"parallel computing\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/\",\"url\":\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/\",\"name\":\"MPL - Collective communication - Number Crunch\",\"isPartOf\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#website\"},\"datePublished\":\"2015-09-01T20:50:52+00:00\",\"dateModified\":\"2023-01-18T21:01:05+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.numbercrunch.de\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"MPL &#8211; Collective communication\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#website\",\"url\":\"https:\/\/www.numbercrunch.de\/blog\/\",\"name\":\"Number Crunch\",\"description\":\"A computational science blog.\",\"publisher\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.numbercrunch.de\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413\",\"name\":\"Heiko Bauke\",\"logo\":{\"@id\":\"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"MPL - Collective communication - Number Crunch","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/","og_locale":"en_US","og_type":"article","og_title":"MPL - Collective communication - Number Crunch","og_description":"In a previous post I gave a very short introduction to the Message Passing Library (MPL), which is a C++ message passing library based on MPI. Although it does not provide a direct mapping of the C API to C++ it comes with all modes of collective communication as defined be the MPI standard, e.g.,&hellip; Continue reading MPL &#8211; Collective communication","og_url":"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/","og_site_name":"Number Crunch","article_published_time":"2015-09-01T20:50:52+00:00","article_modified_time":"2023-01-18T21:01:05+00:00","author":"Heiko Bauke","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Heiko Bauke","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/#article","isPartOf":{"@id":"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/"},"author":{"name":"Heiko Bauke","@id":"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413"},"headline":"MPL &#8211; Collective communication","datePublished":"2015-09-01T20:50:52+00:00","dateModified":"2023-01-18T21:01:05+00:00","mainEntityOfPage":{"@id":"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/"},"wordCount":239,"commentCount":0,"publisher":{"@id":"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413"},"articleSection":["C++","MPI","parallel computing"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/","url":"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/","name":"MPL - Collective communication - Number Crunch","isPartOf":{"@id":"https:\/\/www.numbercrunch.de\/blog\/#website"},"datePublished":"2015-09-01T20:50:52+00:00","dateModified":"2023-01-18T21:01:05+00:00","breadcrumb":{"@id":"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.numbercrunch.de\/blog\/2015\/09\/mpl-collective-communication\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.numbercrunch.de\/blog\/"},{"@type":"ListItem","position":2,"name":"MPL &#8211; Collective communication"}]},{"@type":"WebSite","@id":"https:\/\/www.numbercrunch.de\/blog\/#website","url":"https:\/\/www.numbercrunch.de\/blog\/","name":"Number Crunch","description":"A computational science blog.","publisher":{"@id":"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.numbercrunch.de\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/e73eab65b1721dd0c3d408edb887e413","name":"Heiko Bauke","logo":{"@id":"https:\/\/www.numbercrunch.de\/blog\/#\/schema\/person\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/posts\/697"}],"collection":[{"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/comments?post=697"}],"version-history":[{"count":6,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/posts\/697\/revisions"}],"predecessor-version":[{"id":960,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/posts\/697\/revisions\/960"}],"wp:attachment":[{"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/media?parent=697"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/categories?post=697"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.numbercrunch.de\/blog\/wp-json\/wp\/v2\/tags?post=697"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}