root
root copied to clipboard
Usability of TExecutor::MapReduce
Explain what you would like to see improved
It's hard to use TExecutor::MapReduce correctly, because the required signature of the reducer isn't mentioned in the documentation.
Optional: share how it could be improved
- [ ] Add some info to all docs, e.g. that a lambda like this would do:
[](const std::vector<T>&) { }
Failure to meet that signature leads to an explosion of template instantiation failures with gcc.
- [ ] Show how to do a parallel for using
Map()? - [ ] Mention that
Map()always has to return a dummy value (or: Fix #7872 ) - [ ] Check if TThreadExecutor etc need the same modifications.
To Reproduce
void runParallel() {
ROOT::Internal::TExecutor ex;
const auto nChunk = ROOT::IsImplicitMTEnabled() ? ex.GetPoolSize() : 1u;
// Empty reducer
auto reducer = []() -> int { return 0; };
auto printRange = [=](std::size_t) -> int {
return 0;
};
ex.MapReduce(printRange, ROOT::TSeq<std::size_t>(0, nChunk), reducer, nChunk);
}
Failure to meet that signature leads to an explosion of template instantiation failures with gcc.
We should have better SFINAE code that provides clearer errors
Show how to do a parallel for using Map()?
I think Foreach should be used for that, see my comment at #7872
Adding an static_assert helps a but on the complier error report but it does not stop from trying different instantiations.
In module 'Imt':
/Users/mato/Development/root/builddir/include/ROOT/TExecutor.hxx:240:4: error: static assertion failed due to requirement 'std::is_invocable_v<(lambda at /Users/mato/Development/root/reproducer2.C:5:18), std::vector<int, std::allocator<int> > >': redfunc does not have the correct signature
static_assert(std::is_invocable_v<R, std::vector<InvokeResult_t<F,INTEGER>>>, "redfunc does not have the correct signature");
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/mato/Development/root/reproducer2.C:12:15: note: in instantiation of function template specialization 'ROOT::Internal::TExecutor::MapReduce<(lambda at /Users/mato/Development/root/reproducer2.C:8:21), unsigned long, (lambda at /Users/mato/Development/root/reproducer2.C:5:18), void>' requested here
auto n = ex.MapReduce(printRange, ROOT::TSeq<std::size_t>(0, nChunk), reducer, nChunk);
^
In module 'Imt':
/Users/mato/Development/root/builddir/include/ROOT/TExecutor.hxx:244:11: error: no matching member function for call to 'Reduce'
return Reduce(Map(func, args), redfunc);
^~~~~~
/Users/mato/Development/root/builddir/include/ROOT/TExecutorCRTP.hxx:151:36: note: candidate template ignored: substitution failure [with T = int, R = (lambda at /Users/mato/Development/root/reproducer2.C:5:18)]: no matching function for call to object of type '(lambda at /Users/mato/Development/root/reproducer2.C:5:18)'
template<class T, class R> auto Reduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs));
^ ~~~~~~~
/Users/mato/Development/root/builddir/include/ROOT/TExecutorCRTP.hxx:150:25: note: candidate function not viable: requires single argument 'mergeObjs', but 2 arguments were provided
template<class T> T* Reduce(const std::vector<T*> &mergeObjs);
...