Stride Reference Manual  1.0
tbb.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "unipar.h"
4 #include "interface.h"
5 
6 #include "tbb/parallel_for.h"
7 #include "tbb/task_scheduler_init.h"
8 #include "tbb/enumerable_thread_specific.h"
9 
10 #include <iostream>
11 #include <memory>
12 
13 namespace unipar {
14 namespace internal {
15 
16 template<typename Impl, typename... Types>
18 
19 template<typename Impl, typename Type, typename... Rest>
20 class TbbResourceManager<Impl, Type, Rest...> : public ResourceManager<Impl, Type, Rest...> {
21 public:
22  using RestType = typename Impl::template RMType<Impl, Rest...>;
23  using FuncType = std::function<Type()>;
24  using TLSType = tbb::enumerable_thread_specific<Type>;
25 
26  using ResourceManager<Impl, Type, Rest...>::ResourceManager;
27 
28  template<typename F, typename... Args>
29  typename std::result_of<F(Type&, Args...)>::type call(const F& func, Args&& ... args) {
30  return this->m_rest.call(func, std::forward<Type&>(m_tls->local()), std::forward<Args>(args)...);
31  }
32 
33  void setFunc(const FuncType& f) {
34  this->m_func = f;
35  this->m_tls.reset(new TLSType(f)); // sadly, I can't directly set the function
36  }
37 
38 protected:
39  std::unique_ptr<TLSType> m_tls;
40 };
41 
42 template<typename Impl>
43 class TbbResourceManager<Impl> : public ResourceManager<Impl> {
44 };
45 
46 
48 public:
49  template<typename Impl, typename... Types>
50  using RMType = TbbResourceManager<Impl, Types...>;
51 
52  _TbbParallel(int nthreads = -1) : m_nthreads(nthreads) {}
53 
54  // TBB dislikes manually setting the amount of threads a LOT. In order to not introduce
55  // unexpected behaviour, we can't use task_scheduler_init for this instance, we need to
56  // create one for this call separately.
57  // In order to avoid this overhead, don't manually set the amount of threads or create
58  // a tbb::task_scheduler_init at the start of your program.
59  template<typename IndexF, typename IndexL, typename IndexS, typename Func, typename RM>
60  void parallelFor(IndexF first, IndexL last, IndexS step, const Func& f, RM& rm) {
61  using Largest = typename utils::largest3<IndexF, IndexL, IndexS>::type;
62  auto wrapper = [&](Largest i) {
63  return rm.call(f, i);
64  };
65 
66  if (m_nthreads == -1) {
67  tbb::parallel_for<Largest, decltype(wrapper)>(first, last, step, wrapper);
68  } else {
69  //std::cout << "Limiting to " << m_nthreads << "threads \n";
70  tbb::task_scheduler_init init(m_nthreads);
71  tbb::parallel_for<Largest, decltype(wrapper)>(first, last, step, wrapper);
72  }
73  }
74 
75  inline int getNumThreads() const {
76  if (m_nthreads == -1) {
77  return tbb::task_scheduler_init::default_num_threads();
78  } else {
79  return m_nthreads;
80  }
81  }
82 
83  inline void setNumThreads(int nthreads) { m_nthreads = nthreads; }
84 
85 private:
87 };
88 
89 }
90 
92 
93 }
void parallelFor(IndexF first, IndexL last, IndexS step, const Func &f, RM &rm)
Definition: tbb.h:60
_TbbParallel(int nthreads=-1)
Definition: tbb.h:52
tbb::enumerable_thread_specific< Type > TLSType
Definition: tbb.h:24
void setNumThreads(int nthreads)
Definition: tbb.h:83
Unified Parallelisation.
Definition: dummy.h:7
int getNumThreads() const
Definition: tbb.h:75
is_cond<(sizeof(_type_temp) > sizeof(T3)), _type_temp, T3 >::type type
typename Impl::template RMType< Impl, Rest... > RestType
Definition: tbb.h:22
std::result_of< F(Type &, Args...)>::type call(const F &func, Args &&...args)
Definition: tbb.h:29