#pragma once #include "launch.hpp" namespace tf { // Function: make_transform_task template < typename B, typename E, typename O, typename C, typename P = DefaultPartitioner, std::enable_if_t>, void>* = nullptr > auto make_transform_task(B first1, E last1, O d_first, C c, P part = P()) { using B_t = std::decay_t>; using E_t = std::decay_t>; using O_t = std::decay_t>; return [=] (Runtime& rt) mutable { // fetch the stateful values B_t beg = first1; E_t end = last1; O_t d_beg = d_first; size_t W = rt.executor().num_workers(); size_t N = std::distance(beg, end); // only myself - no need to spawn another graph if(W <= 1 || N <= part.chunk_size()) { launch_loop(part, [&](){ std::transform(beg, end, d_beg, c); }); return; } if(N < W) { W = N; } // static partitioner if constexpr(part.type() == PartitionerType::STATIC) { size_t chunk_size; for(size_t w=0, curr_b=0; w next(0); launch_loop(N, W, rt, next, part, [=, &next, &part] () mutable { part.loop(N, W, next, [&, prev_e=size_t{0}](size_t part_b, size_t part_e) mutable { std::advance(beg, part_b - prev_e); std::advance(d_beg, part_b - prev_e); for(size_t x = part_b; x>, void>* = nullptr > auto make_transform_task(B1 first1, E1 last1, B2 first2, O d_first, C c, P part = P()) { using B1_t = std::decay_t>; using E1_t = std::decay_t>; using B2_t = std::decay_t>; using O_t = std::decay_t>; return [=] (Runtime& rt) mutable { // fetch the stateful values B1_t beg1 = first1; E1_t end1 = last1; B2_t beg2 = first2; O_t d_beg = d_first; size_t W = rt.executor().num_workers(); size_t N = std::distance(beg1, end1); // only myself - no need to spawn another graph if(W <= 1 || N <= part.chunk_size()) { launch_loop(part, [&](){ std::transform(beg1, end1, beg2, d_beg, c); }); return; } if(N < W) { W = N; } // static partitioner if constexpr(part.type() == PartitionerType::STATIC) { size_t chunk_size; for(size_t w=0, curr_b=0; w next(0); launch_loop(N, W, rt, next, part, [=, &c, &next, &part] () mutable { part.loop(N, W, next, [&, prev_e=size_t{0}](size_t part_b, size_t part_e) mutable { std::advance(beg1, part_b - prev_e); std::advance(beg2, part_b - prev_e); std::advance(d_beg, part_b - prev_e); for(size_t x = part_b; x>, void>* > Task FlowBuilder::transform(B first1, E last1, O d_first, C c, P part) { return emplace( make_transform_task(first1, last1, d_first, c, part) ); } // ---------------------------------------------------------------------------- // transform2 // ---------------------------------------------------------------------------- // Function: transform template < typename B1, typename E1, typename B2, typename O, typename C, typename P, std::enable_if_t>, void>* > Task FlowBuilder::transform( B1 first1, E1 last1, B2 first2, O d_first, C c, P part ) { return emplace(make_transform_task( first1, last1, first2, d_first, c, part )); } } // end of namespace tf -----------------------------------------------------