# include <tbb/partitioner.h>
#endif
+#ifdef DEAL_II_HAVE_CXX20
+# include <concepts>
+#endif
+
// TODO[WB]: allow calling functions to pass along a tbb::affinity_partitioner
// object to ensure that subsequent calls use the same cache lines
/**
* An algorithm that performs the action <code>*out++ =
- * predicate(*in++)</code> where the <code>in</code> iterator ranges over
+ * function(*in++)</code> where the <code>in</code> iterator ranges over
* the given input range.
*
* This algorithm does pretty much what std::transform does. The difference
* @ref threads "Parallel computing with multiple processors"
* module.
*/
- template <typename InputIterator, typename OutputIterator, typename Predicate>
- void
- transform(const InputIterator &begin_in,
- const InputIterator &end_in,
- OutputIterator out,
- const Predicate & predicate,
- const unsigned int grainsize)
+ template <typename InputIterator, typename OutputIterator, typename Function>
+ DEAL_II_CXX20_REQUIRES((std::invocable<Function, InputIterator>))
+ void transform(const InputIterator &begin_in,
+ const InputIterator &end_in,
+ OutputIterator out,
+ const Function & function,
+ const unsigned int grainsize)
{
#ifndef DEAL_II_WITH_TBB
// make sure we don't get compiler
(void)grainsize;
for (OutputIterator in = begin_in; in != end_in;)
- *out++ = predicate(*in++);
+ *out++ = function(*in++);
#else
using Iterators = std::tuple<InputIterator, OutputIterator>;
using SyncIterators = SynchronousIterators<Iterators>;
internal::parallel_for(
SyncIterators(x_begin),
SyncIterators(x_end),
- [predicate](const auto &range) {
+ [function](const auto &range) {
for (const auto &p : range)
- *std::get<1>(p) = predicate(*std::get<0>(p));
+ *std::get<1>(p) = function(*std::get<0>(p));
},
grainsize);
#endif
/**
- * An algorithm that performs the action <code>*out++ = predicate(*in1++,
+ * An algorithm that performs the action <code>*out++ = function(*in1++,
* *in2++)</code> where the <code>in1</code> iterator ranges over the given
* input range, using the parallel for operator of tbb.
*
template <typename InputIterator1,
typename InputIterator2,
typename OutputIterator,
- typename Predicate>
- void
- transform(const InputIterator1 &begin_in1,
- const InputIterator1 &end_in1,
- InputIterator2 in2,
- OutputIterator out,
- const Predicate & predicate,
- const unsigned int grainsize)
+ typename Function>
+ DEAL_II_CXX20_REQUIRES(
+ (std::invocable<Function, InputIterator1, InputIterator2>))
+ void transform(const InputIterator1 &begin_in1,
+ const InputIterator1 &end_in1,
+ InputIterator2 in2,
+ OutputIterator out,
+ const Function & function,
+ const unsigned int grainsize)
{
#ifndef DEAL_II_WITH_TBB
// make sure we don't get compiler
(void)grainsize;
for (OutputIterator in1 = begin_in1; in1 != end_in1;)
- *out++ = predicate(*in1++, *in2++);
+ *out++ = function(*in1++, *in2++);
#else
using Iterators =
std::tuple<InputIterator1, InputIterator2, OutputIterator>;
internal::parallel_for(
SyncIterators(x_begin),
SyncIterators(x_end),
- [predicate](const auto &range) {
+ [function](const auto &range) {
for (const auto &p : range)
- *std::get<2>(p) = predicate(*std::get<0>(p), *std::get<1>(p));
+ *std::get<2>(p) = function(*std::get<0>(p), *std::get<1>(p));
},
grainsize);
#endif
/**
- * An algorithm that performs the action <code>*out++ = predicate(*in1++,
+ * An algorithm that performs the action <code>*out++ = function(*in1++,
* *in2++, *in3++)</code> where the <code>in1</code> iterator ranges over
* the given input range.
*
typename InputIterator2,
typename InputIterator3,
typename OutputIterator,
- typename Predicate>
- void
- transform(const InputIterator1 &begin_in1,
- const InputIterator1 &end_in1,
- InputIterator2 in2,
- InputIterator3 in3,
- OutputIterator out,
- const Predicate & predicate,
- const unsigned int grainsize)
+ typename Function>
+ DEAL_II_CXX20_REQUIRES(
+ (std::invocable<Function, InputIterator1, InputIterator2, InputIterator3>))
+ void transform(const InputIterator1 &begin_in1,
+ const InputIterator1 &end_in1,
+ InputIterator2 in2,
+ InputIterator3 in3,
+ OutputIterator out,
+ const Function & function,
+ const unsigned int grainsize)
{
#ifndef DEAL_II_WITH_TBB
// make sure we don't get compiler
(void)grainsize;
for (OutputIterator in1 = begin_in1; in1 != end_in1;)
- *out++ = predicate(*in1++, *in2++, *in3++);
+ *out++ = function(*in1++, *in2++, *in3++);
#else
using Iterators = std::
tuple<InputIterator1, InputIterator2, InputIterator3, OutputIterator>;
internal::parallel_for(
SyncIterators(x_begin),
SyncIterators(x_end),
- [predicate](const auto &range) {
+ [function](const auto &range) {
for (const auto &p : range)
*std::get<3>(p) =
- predicate(*std::get<0>(p), *std::get<1>(p), *std::get<2>(p));
+ function(*std::get<0>(p), *std::get<1>(p), *std::get<2>(p));
},
grainsize);
#endif
* Take a range argument and call the given function with its begin and
* end.
*/
- template <typename RangeType, typename Function>
- void
- apply_to_subranges(const tbb::blocked_range<RangeType> &range,
- const Function & f)
+ template <typename Iterator, typename Function>
+ DEAL_II_CXX20_REQUIRES((std::invocable<Function, Iterator, Iterator>))
+ void apply_to_subranges(const tbb::blocked_range<Iterator> &range,
+ const Function & f)
{
f(range.begin(), range.end());
}
* @ref threads "Parallel computing with multiple processors"
* module.
*/
- template <typename RangeType, typename Function>
- void
- apply_to_subranges(const RangeType & begin,
- const typename identity<RangeType>::type &end,
- const Function & f,
- const unsigned int grainsize)
+ template <typename Iterator, typename Function>
+ DEAL_II_CXX20_REQUIRES((std::invocable<Function, Iterator, Iterator>))
+ void apply_to_subranges(const Iterator & begin,
+ const typename identity<Iterator>::type &end,
+ const Function & f,
+ const unsigned int grainsize)
{
#ifndef DEAL_II_WITH_TBB
// make sure we don't get compiler
internal::parallel_for(
begin,
end,
- [&f](const tbb::blocked_range<RangeType> &range) {
- internal::apply_to_subranges<RangeType, Function>(range, f);
+ [&f](const tbb::blocked_range<Iterator> &range) {
+ internal::apply_to_subranges<Iterator, Function>(range, f);
},
grainsize);
#endif
* @ref threads "Parallel computing with multiple processors"
* module.
*/
- template <typename ResultType, typename RangeType, typename Function>
+ template <typename ResultType, typename Iterator, typename Function>
+ DEAL_II_CXX20_REQUIRES((std::invocable<Function, Iterator, Iterator>))
ResultType
- accumulate_from_subranges(const Function & f,
- const RangeType & begin,
- const typename identity<RangeType>::type &end,
- const unsigned int grainsize)
+ accumulate_from_subranges(const Function & f,
+ const Iterator & begin,
+ const typename identity<Iterator>::type &end,
+ const unsigned int grainsize)
{
#ifndef DEAL_II_WITH_TBB
// make sure we don't get compiler
return f(begin, end);
#else
return tbb::parallel_reduce(
- tbb::blocked_range<RangeType>(begin, end, grainsize),
+ tbb::blocked_range<Iterator>(begin, end, grainsize),
ResultType(0),
[f](const auto &range, const ResultType &starting_value) {
ResultType value = starting_value;