{"id":5252,"date":"2017-05-01T19:54:25","date_gmt":"2017-05-01T19:54:25","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-17-new-algorithm-of-the-standard-template-library\/"},"modified":"2023-06-26T12:17:22","modified_gmt":"2023-06-26T12:17:22","slug":"c-17-new-algorithm-of-the-standard-template-library","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-17-new-algorithm-of-the-standard-template-library\/","title":{"rendered":"C++17: New Parallel Algorithms of the Standard Template Library"},"content":{"rendered":"<p>The idea is quite simple. The Standard Template (STL) has more than 100 algorithms for searching, counting, and manipulating ranges and their elements. With C++17, 69 are overloaded, and a few new ones are added. The overloaded and new algorithm can be invoked with a so-called execution policy. By using the execution policy, you can specify whether the algorithm should run sequentially, parallel, or parallel and vectorized.<\/p>\n<p><!--more--><\/p>\n<p>My previous post was mainly about overloaded algorithms. If you are curious, read the post<a href=\"https:\/\/www.modernescpp.com\/index.php\/parallel-algorithm-of-the-standard-template-library\"> Parallel Algorithm of the Standard Template Library<\/a>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4724\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/04\/timeline.png\" alt=\"timeline\" width=\"700\" height=\"338\" style=\"margin: 15px;\" \/><\/p>\n<p>Today, I&#8217;m writing about the seven new algorithms. Here are they.<\/p>\n<div style=\"background: #f0f3f3 none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\">std<span style=\"color: #555555;\">::<\/span>for_each_n\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>exclusive_scan\r\nstd<span style=\"color: #555555;\">::<\/span>inclusive_scan\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>transform_exclusive_scan\r\nstd<span style=\"color: #555555;\">::<\/span>transform_inclusive_scan\r\n\r\nstd<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>reduce\r\nstd<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>transform_reduce\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Besides <span style=\"font-family: courier new,courier;\">std::for_each_n<\/span> these names are pretty unusual. So let me make a short detour and write about Haskell.<\/p>\n<\/p>\n<h2>A short detour<\/h2>\n<p>To make the long story short. All new functions have a pendant in the pure functional language Haskell.<\/p>\n<ul>\n<li><span style=\"font-family: Courier New,Courier,monospace;\">for_each_n<\/span> is called <span style=\"font-family: Courier New,Courier,monospace;\">map <\/span>in Haskell.<\/li>\n<li><span style=\"font-family: Courier New,Courier,monospace;\">exclusive_scan<\/span> and <span style=\"font-family: Courier New,Courier,monospace;\">inclusive_scan<\/span> are called<span style=\"font-family: Courier New,Courier,monospace;\"> scanl<\/span> and <span style=\"font-family: Courier New,Courier,monospace;\">scanl1<\/span> in Haskell.<\/li>\n<li><span style=\"font-family: Courier New,Courier,monospace;\">transform_exclusive_scan<\/span> and <span style=\"font-family: Courier New,Courier,monospace;\">transform_inclusive_scan<\/span> is a composition of the Haskell functions <span style=\"font-family: Courier New,Courier,monospace;\">map<\/span> and <span style=\"font-family: Courier New,Courier,monospace;\">scanl<\/span> or <span style=\"font-family: Courier New,Courier,monospace;\">scanl1<\/span>.<\/li>\n<li><span style=\"font-family: Courier New,Courier,monospace;\">reduce <\/span>is called <span style=\"font-family: Courier New,Courier,monospace;\">foldl <\/span>or <span style=\"font-family: Courier New,Courier,monospace;\">foldl1 <\/span>in Haskell.<\/li>\n<li><span style=\"font-family: Courier New,Courier,monospace;\">transform_reduce<\/span> is a composition of the Haskell functions <span style=\"font-family: Courier New,Courier,monospace;\">map <\/span>and <span style=\"font-family: Courier New,Courier,monospace;\">foldl <\/span>or <span style=\"font-family: Courier New,Courier,monospace;\">foldl1<\/span>.<\/li>\n<\/ul>\n<p>Before I show you Haskell in action, let me describe the different functions.<\/p>\n<ul>\n<li><span style=\"font-family: Courier New,Courier,monospace;\">map <\/span>applies a function to a list.<\/li>\n<li><span style=\"font-family: Courier New,Courier,monospace;\">foldl <\/span>and <span style=\"font-family: Courier New,Courier,monospace;\">foldl1 <\/span>apply a binary operation to a list and reduces the list to a value. <span style=\"font-family: Courier New,Courier,monospace;\">foldl <\/span>needs contrary to <span style=\"font-family: Courier New,Courier,monospace;\">foldl1 <\/span>an initial value.<\/li>\n<li><span style=\"font-family: Courier New,Courier,monospace;\">scanl <\/span>and <span style=\"font-family: Courier New,Courier,monospace;\">scanl1 <\/span>apply the same strategy such as <span style=\"font-family: Courier New,Courier,monospace;\">foldl <\/span>and <span style=\"font-family: Courier New,Courier,monospace;\">foldl1, <\/span>but they produce all intermediate values. So you get back a list.<\/li>\n<li><span style=\"font-family: courier new,courier;\">foldl<\/span>, <span style=\"font-family: courier new,courier;\">foldl1<\/span>,<span style=\"font-family: courier new,courier;\"> scanl<\/span>, and <span style=\"font-family: courier new,courier;\">scanl1<\/span> start their job from the left.<\/li>\n<\/ul>\n<p>Now comes the action. Here is Haskell&#8217;s interpreter shell.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5250\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/newAlgorithmHaskell.png\" alt=\"newAlgorithmHaskell\" style=\"margin: 15px;\" width=\"636\" height=\"496\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/newAlgorithmHaskell.png 636w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/newAlgorithmHaskell-300x234.png 300w\" sizes=\"auto, (max-width: 636px) 100vw, 636px\" \/><\/p>\n<p>(1) and (2) define a list of integers and a list of strings. In (3), I apply the lambda function (<span style=\"font-family: Courier New,Courier,monospace;\">\\a -&gt; a * <\/span>a) to the list of <span style=\"font-family: Courier New,Courier,monospace;\">ints<\/span>. (4) and (5) are more sophisticated. The expression (4) multiplies (*) all pairs of integers, starting with 1 as a neutral multiplication element.&nbsp; Expression (5) does the corresponding for the addition. The expressions (6), (7), and (9) are quite challenging to read for the imperative eye. You have to read them from right to left. <span style=\"font-family: Courier New,Courier,monospace;\">scanl1 (+) . map(\\a -&gt; length a (7)<\/span> is a function composition. The dot (.) symbol composes the two functions. The first function maps each element to its length. The second function adds the list of lengths together. (9) is similar to 7. The difference is that <span style=\"font-family: Courier New,Courier,monospace;\">foldl <\/span>produces one value and requires an initial element. This is 0. Now, the expression (8) should be readable. The expression successively joins two strings with the &#8220;<span style=\"font-family: Courier New,Courier,monospace;\">:<\/span>&#8221; character.&nbsp;<\/p>\n<p>You wonder why I write in a C++ blog so much challenging stuff about Haskell. That is for two good reasons. First, you know the history of C++ functions. And second,&nbsp; it&#8217;s a lot easier to understand the C++ function if you compare them with the Haskell pendants.<\/p>\n<p>So, let&#8217;s finally start with C++.<\/p>\n<h2>The seven new algorithms<\/h2>\n<p>I promised it may become a little bit difficult to read.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ newAlgorithm.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;hpx\/hpx_init.hpp&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;hpx\/hpx.hpp&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;hpx\/include\/parallel_numeric.hpp&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;hpx\/include\/parallel_algorithm.hpp&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;hpx\/include\/iostreams.hpp&gt;<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;vector&gt;<\/span>\r\n\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">hpx_main<\/span>(){\r\n  \r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> hpx<span style=\"color: #555555;\">::<\/span>endl;\r\n  \r\n  <span style=\"color: #0099ff; font-style: italic;\">\/\/ for_each_n<\/span>\r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> intVec{<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">5<\/span>, <span style=\"color: #ff6600;\">6<\/span>, <span style=\"color: #ff6600;\">7<\/span>, <span style=\"color: #ff6600;\">8<\/span>, <span style=\"color: #ff6600;\">9<\/span>, <span style=\"color: #ff6600;\">10<\/span>};                        <span style=\"color: #0099ff; font-style: italic;\">\/\/ 1<\/span>\r\n  hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>for_each_n(hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>execution<span style=\"color: #555555;\">::<\/span>par,                       <span style=\"color: #0099ff; font-style: italic;\">\/\/ 2<\/span>\r\n                            intVec.begin(), <span style=\"color: #ff6600;\">5<\/span>, [](<span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;<\/span> arg){ arg <span style=\"color: #555555;\">*=<\/span> arg; });\r\n  \r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"for_each_n: \"<\/span>;\r\n  <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> v<span style=\"color: #555555;\">:<\/span> intVec) hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> v <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;\r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n  \r\n  <span style=\"color: #0099ff; font-style: italic;\">\/\/ exclusive_scan and inclusive_scan<\/span>\r\n  std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> resVec{<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">5<\/span>, <span style=\"color: #ff6600;\">6<\/span>, <span style=\"color: #ff6600;\">7<\/span>, <span style=\"color: #ff6600;\">8<\/span>, <span style=\"color: #ff6600;\">9<\/span>};\r\n  hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>exclusive_scan(hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>execution<span style=\"color: #555555;\">::<\/span>par,                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ 3<\/span>\r\n                               resVec.begin(), resVec.end(), resVec.begin(), <span style=\"color: #ff6600;\">1<\/span>,\r\n                               [](<span style=\"color: #007788; font-weight: bold;\">int<\/span> fir, <span style=\"color: #007788; font-weight: bold;\">int<\/span> sec){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> fir <span style=\"color: #555555;\">*<\/span> sec; });\r\n  \r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"exclusive_scan: \"<\/span>;\r\n  <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> v<span style=\"color: #555555;\">:<\/span> resVec) hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> v <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;\r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> hpx<span style=\"color: #555555;\">::<\/span>endl; \r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> resVec2{<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">5<\/span>, <span style=\"color: #ff6600;\">6<\/span>, <span style=\"color: #ff6600;\">7<\/span>, <span style=\"color: #ff6600;\">8<\/span>, <span style=\"color: #ff6600;\">9<\/span>};\r\n  \r\n  hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>inclusive_scan(hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>execution<span style=\"color: #555555;\">::<\/span>par,                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ 5 <\/span>\r\n                      resVec2.begin(), resVec2.end(), resVec2.begin(),        \r\n                      [](<span style=\"color: #007788; font-weight: bold;\">int<\/span> fir, <span style=\"color: #007788; font-weight: bold;\">int<\/span> sec){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> fir <span style=\"color: #555555;\">*<\/span> sec; }, <span style=\"color: #ff6600;\">1<\/span>);\r\n  \r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"inclusive_scan: \"<\/span>;\r\n  <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> v<span style=\"color: #555555;\">:<\/span> resVec2) hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> v <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;\r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n  \r\n  <span style=\"color: #0099ff; font-style: italic;\">\/\/ transform_exclusive_scan and transform_inclusive_scan<\/span>\r\n  std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> resVec3{<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">5<\/span>, <span style=\"color: #ff6600;\">6<\/span>, <span style=\"color: #ff6600;\">7<\/span>, <span style=\"color: #ff6600;\">8<\/span>, <span style=\"color: #ff6600;\">9<\/span>};\r\n  std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> resVec4(resVec3.size());             \r\n  hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>transform_exclusive_scan(hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>execution<span style=\"color: #555555;\">::<\/span>par,         <span style=\"color: #0099ff; font-style: italic;\">\/\/ 6<\/span>\r\n                                          resVec3.begin(), resVec3.end(), \r\n                                          resVec4.begin(), <span style=\"color: #ff6600;\">0<\/span>,\r\n                                          [](<span style=\"color: #007788; font-weight: bold;\">int<\/span> fir, <span style=\"color: #007788; font-weight: bold;\">int<\/span> sec){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> fir <span style=\"color: #555555;\">+<\/span> sec; },\r\n                                          [](<span style=\"color: #007788; font-weight: bold;\">int<\/span> arg){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> arg <span style=\"color: #555555;\">*=<\/span> arg; });\r\n  \r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"transform_exclusive_scan: \"<\/span>;\r\n  <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> v<span style=\"color: #555555;\">:<\/span> resVec4) hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> v <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;\r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> hpx<span style=\"color: #555555;\">::<\/span>endl;\r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&gt;<\/span> strVec{<span style=\"color: #cc3300;\">\"Only\"<\/span>,<span style=\"color: #cc3300;\">\"for\"<\/span>,<span style=\"color: #cc3300;\">\"testing\"<\/span>,<span style=\"color: #cc3300;\">\"purpose\"<\/span>};             <span style=\"color: #0099ff; font-style: italic;\">\/\/ 7<\/span>\r\n  std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> resVec5(strVec.size());\r\n  \r\n  hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>transform_inclusive_scan(hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>execution<span style=\"color: #555555;\">::<\/span>par,         <span style=\"color: #0099ff; font-style: italic;\">\/\/ 8<\/span>\r\n                                          strVec.begin(), strVec.end(), \r\n                                          resVec5.begin(), <span style=\"color: #ff6600;\">0<\/span>,\r\n                                          [](<span style=\"color: #006699; font-weight: bold;\">auto<\/span> fir, <span style=\"color: #006699; font-weight: bold;\">auto<\/span> sec){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> fir <span style=\"color: #555555;\">+<\/span> sec; },\r\n                                          [](<span style=\"color: #006699; font-weight: bold;\">auto<\/span> s){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> s.length(); });\r\n                                  \r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"transform_inclusive_scan: \"<\/span>;\r\n  <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> v<span style=\"color: #555555;\">:<\/span> resVec5) hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> v <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;\r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\r\n  \r\n  <span style=\"color: #0099ff; font-style: italic;\">\/\/ reduce and transform_reduce<\/span>\r\n  std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&gt;<\/span> strVec2{<span style=\"color: #cc3300;\">\"Only\"<\/span>,<span style=\"color: #cc3300;\">\"for\"<\/span>,<span style=\"color: #cc3300;\">\"testing\"<\/span>,<span style=\"color: #cc3300;\">\"purpose\"<\/span>};\r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>string res <span style=\"color: #555555;\">=<\/span> hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>reduce(hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>execution<span style=\"color: #555555;\">::<\/span>par,         <span style=\"color: #0099ff; font-style: italic;\">\/\/ 9<\/span>\r\n                    strVec2.begin() <span style=\"color: #555555;\">+<\/span> <span style=\"color: #ff6600;\">1<\/span>, strVec2.end(), strVec2[<span style=\"color: #ff6600;\">0<\/span>], \r\n                    [](<span style=\"color: #006699; font-weight: bold;\">auto<\/span> fir, <span style=\"color: #006699; font-weight: bold;\">auto<\/span> sec){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> fir <span style=\"color: #555555;\">+<\/span> <span style=\"color: #cc3300;\">\":\"<\/span> <span style=\"color: #555555;\">+<\/span> sec; });\r\n  \r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"reduce: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> res <span style=\"color: #555555;\">&lt;&lt;<\/span> hpx<span style=\"color: #555555;\">::<\/span>endl;\r\n \r\n                                                                                 <span style=\"color: #0099ff; font-style: italic;\">\/\/ 11<\/span>\r\n  std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> res7 <span style=\"color: #555555;\">=<\/span> hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>transform_reduce(hpx<span style=\"color: #555555;\">::<\/span>parallel<span style=\"color: #555555;\">::<\/span>execution<span style=\"color: #555555;\">::<\/span>par,        \r\n                     strVec2.begin(), strVec2.end(), \r\n                     [](std<span style=\"color: #555555;\">::<\/span>string s){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> s.length(); }, \r\n                     <span style=\"color: #ff6600;\">0<\/span>, [](std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> a, std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> b){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> a <span style=\"color: #555555;\">+<\/span> b; });                                                                          \r\n    \r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"transform_reduce: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> res7 <span style=\"color: #555555;\">&lt;&lt;<\/span> hpx<span style=\"color: #555555;\">::<\/span>endl;\r\n  \r\n  hpx<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> hpx<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n  <span style=\"color: #006699; font-weight: bold;\">return<\/span> hpx<span style=\"color: #555555;\">::<\/span>finalize();\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> argc, <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">*<\/span> argv[]){\r\n  \r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ By default this should run on all available cores<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&gt;<\/span> <span style=\"color: #006699; font-weight: bold;\">const<\/span> cfg <span style=\"color: #555555;\">=<\/span> {<span style=\"color: #cc3300;\">\"hpx.os_threads=all\"<\/span>};\r\n\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ Initialize and run HPX<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> hpx<span style=\"color: #555555;\">::<\/span>init(argc, argv, cfg);\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Before I show you the program&#8217;s output and explain the source code, I must make a general remark. As far as I know, no parallel STL implementation is available. Therefore, I used the <a href=\"http:\/\/stellar-group.org\/2017\/04\/hpx-v1-0-released\/\">HPX<\/a> implementation that uses the namespace <span style=\"font-family: Courier New,Courier,monospace;\">hpx<\/span>. So, if you replace the namespace <span style=\"font-family: Courier New,Courier,monospace;\">hpx <\/span>with <span style=\"font-family: Courier New,Courier,monospace;\">std <\/span>and write the code in the <span style=\"font-family: Courier New,Courier,monospace;\">hpx_main <\/span>function, you know what the STL algorithm will look like.&nbsp;<\/p>\n<p>In correspondence to Haskell, I use a <span style=\"font-family: Courier New,Courier,monospace;\">std::vector<\/span> of ints (1) and strings (7).&nbsp;<\/p>\n<p>The <span style=\"font-family: courier new,courier;\">for_each_n<\/span> algorithm in (2) maps the first n <span style=\"font-family: courier new,courier;\">ints<\/span> of the vector to its power of 2.<\/p>\n<p><span style=\"font-family: courier new,courier;\">exclusive_scan<\/span> (3) and <span style=\"font-family: courier new,courier;\">inclusive_scan<\/span> (5) are pretty similar. Both apply a binary operation to their elements. The difference is that <span style=\"font-family: courier new,courier;\">exclusive_scan<\/span> excludes in each iteration the last element. You have the corresponding Haskell expression: <span style=\"font-family: Courier New,Courier,monospace;\">scanl (*) 1 ints<\/span>.<\/p>\n<p>The <span style=\"font-family: courier new,courier;\">transform_exclusive_scan<\/span> (6) is quite challenging to read. Let me try it. Apply in the first step the lambda function<span style=\"font-family: Courier New,Courier,monospace;\"> [](int arg){ return arg *= arg; } <\/span>to each element of the range from <span style=\"font-family: Courier New,Courier,monospace;\">resVec3.begin() <\/span>to <span style=\"font-family: Courier New,Courier,monospace;\">resVec3.end()<\/span>. Then apply in the second step the binary operation <span style=\"font-family: Courier New,Courier,monospace;\">[](int fir, int sec){ return fir + sec; } <\/span>to the intermediate vector. That means summing up all elements by using 0 as the initial element. The result goes to <span style=\"font-family: Courier New,Courier,monospace;\">resVec4.begin()<\/span>. To make the long story short. Here is Haskell:<span style=\"font-family: Courier New,Courier,monospace;\"> scanl (+) 0 . map(\\a -&gt; a * a) $ ints. <\/span><\/p>\n<p>The<span style=\"font-family: Courier New,Courier,monospace;\"> transform_inclusive_scan<\/span> function in (8) is similar. This function maps each element to its length. Once more in Haskell: <span style=\"font-family: Courier New,Courier,monospace;\">scanl1 (+) . map(\\a -&gt; length a) $ strings. <\/span><\/p>\n<p>Now, the reduce function should be pretty simple to read. It puts &#8220;:&#8221; characters between each element of the input vector. The resulting string should not start with a &#8220;<span style=\"font-family: Courier New,Courier,monospace;\">:<\/span>&#8221; character. Therefore, the range starts at the second element (<span style=\"font-family: Courier New,Courier,monospace;\">strVec2.begin() + 1<\/span>), and the initial element is the first element of the vector: <span style=\"font-family: Courier New,Courier,monospace;\">strVec2[0]<\/span>. Here is Haskell:<span style=\"font-family: Courier New,Courier,monospace;\"> foldl1 (\\l r -&gt; l ++ &#8220;:&#8221; ++ r) strings. <\/span><\/p>\n<p>If you want to understand the <span style=\"font-family: courier new,courier;\">transform_reduce <\/span>expression in (11), please read my post&nbsp;<a href=\"https:\/\/www.modernescpp.com\/index.php\/parallel-algorithm-of-the-standard-template-library\"> Parallel Algorithm of the Standard Template Library.<\/a> I have more to say about the function. For the impatient readers. The concise expression in Haskell: <span style=\"font-family: Courier New,Courier,monospace;\">foldl (+) 0 . map (\\a -&gt; length a) $ strings.<\/span><\/p>\n<p>Studying the output of the program should help you.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5251\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/newAlgorithm.png\" alt=\"newAlgorithm\" style=\"margin: 15px;\" width=\"636\" height=\"295\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/newAlgorithm.png 636w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/05\/newAlgorithm-300x139.png 300w\" sizes=\"auto, (max-width: 636px) 100vw, 636px\" \/><\/p>\n<h2>Final remarks<\/h2>\n<p>Each of the seven new algorithms exists in different flavors. You can invoke them with and without an initial element, with and without specifying the execution policy. You can invoke the function&nbsp;that requires a binary operator, such as <span style=\"font-family: courier new,courier;\">std::scan<\/span> and <span style=\"font-family: courier new,courier;\">std::parallel::reduce<\/span>, even without a binary operator. In this case, the addition is used as default. The binary operator must be associative to execute the algorithm in parallel or in parallel and vectorized. That makes excellent sense because the algorithm can efficiently run on many cores. For the details, read the Wikipedia article on <a href=\"https:\/\/en.wikipedia.org\/wiki\/Prefix_sum\">prefix_sum<\/a>. Here are further details about the new algorithms: <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/experimental\/parallelism\">extensions for parallelism<\/a>.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Sorry, that was a long post. But making two posts out of it makes no sense. In the<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-17-the-improved-interface-of-the-associative-containers\"> next post<\/a>, I will write about the performance-improved interface of the associative containers (sets and maps) and the unified interface of the STL containers at.<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The idea is quite simple. The Standard Template (STL) has more than 100 algorithms for searching, counting, and manipulating ranges and their elements. With C++17, 69 are overloaded, and a few new ones are added. The overloaded and new algorithm can be invoked with a so-called execution policy. By using the execution policy, you can [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":4724,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[370],"tags":[508],"class_list":["post-5252","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-17","tag-haskell"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5252","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5252"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5252\/revisions"}],"predecessor-version":[{"id":6874,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5252\/revisions\/6874"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/4724"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5252"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5252"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5252"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}