This problem is easier to explain with a simplified example (since my real situation is far from being “minimal”): considering ...
template <typename T>
void post_in_thread_pool(T&& f)
... function template, I want to create a parallel asynchronous algorithm that has a tree-like recursive structure. I am going to write an example of the structure below, using std::count_if
as a placeholder. The strategy I'm going to use is as follows:
If the length of the range that I am checking is less than 64
, I will return to the sequential function std::count_if
. (0)
If it is greater than or equal 64
, I will create a task in the thread pool that will return to the left half of the range and calculate the right half of the range of the current thread. (one)
Simplified code:
auto async_count_if(auto begin, auto end, auto predicate, auto continuation)
{
if(end - begin < 64)
{
continuation(std::count_if(begin, end, predicate));
return;
}
auto counter = make_shared<atomic<int>>(2);
auto cleanup = [=, accumulator = make_shared<atomic<int>>(0) ]
(int partial_result)
{
*accumulator += partial_result;
if(--*counter == 0)
{
continuation(*accumulator);
}
};
const auto mid = std::next(i_begin, sz / 2);
post_in_thread_pool([=]
{
async_count_if(i_begin, mid, predicate, cleanup);
});
async_count_if(mid, i_end, predicate, cleanup);
}
Then the code can be used as follows:
std::vector<int> v(512);
std::iota(std::begin(v), std::end(v), 0);
async_count_if{}(std::begin(v), std::end(v),
[](auto x){ return x < 256; },
[](auto res){ std::cout << res << std::endl; });
The problem is in the above code auto cleanup
. Since it auto
will be displayed on a unique type for each cleanup
lambda instance , and since the cleanup
capture cont
by value ... an infinitely large nested lambda type will be computed at compile time due to recursion, resulting in the following error:
: 1024
wandbox
, , :
cont
cleanup0<cont>
cleanup1<cleanup0<cont>>
cleanup2<cleanup1<cleanup0<cont>>>
(!): , async_count_if
- , "" . , count_if
sz / 64
.
, .
, , async_count_if
: std::distance(i_begin, i_end)
. , : (2^k - 1)
, k
- .
, " " async_count_if
. " " (2^k - 1)
(2^k - 1)
/.
, , , , , .
, ?