parallel_for.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "../tasking/taskscheduler.h"
  5. #include "../sys/array.h"
  6. #include "../math/emath.h"
  7. #include "../math/range.h"
  8. namespace embree
  9. {
  10. /* parallel_for without range */
  11. template<typename Index, typename Func>
  12. __forceinline void parallel_for( const Index N, const Func& func)
  13. {
  14. #if defined(TASKING_INTERNAL) && !defined(TASKING_TBB)
  15. if (N) {
  16. TaskScheduler::TaskGroupContext context;
  17. TaskScheduler::spawn(Index(0),N,Index(1),[&] (const range<Index>& r) {
  18. assert(r.size() == 1);
  19. func(r.begin());
  20. },&context);
  21. TaskScheduler::wait();
  22. if (context.cancellingException != nullptr) {
  23. std::rethrow_exception(context.cancellingException);
  24. }
  25. }
  26. #elif defined(TASKING_TBB)
  27. #if TBB_INTERFACE_VERSION >= 12002
  28. tbb::task_group_context context;
  29. tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
  30. func(i);
  31. },context);
  32. if (context.is_group_execution_cancelled())
  33. throw std::runtime_error("task cancelled");
  34. #else
  35. tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
  36. func(i);
  37. });
  38. if (tbb::task::self().is_cancelled())
  39. throw std::runtime_error("task cancelled");
  40. #endif
  41. #elif defined(TASKING_PPL)
  42. concurrency::parallel_for(Index(0),N,Index(1),[&](Index i) {
  43. func(i);
  44. });
  45. #else
  46. # error "no tasking system enabled"
  47. #endif
  48. }
  49. /* parallel for with range and granulatity */
  50. template<typename Index, typename Func>
  51. __forceinline void parallel_for( const Index first, const Index last, const Index minStepSize, const Func& func)
  52. {
  53. assert(first <= last);
  54. #if defined(TASKING_INTERNAL) && !defined(TASKING_TBB)
  55. TaskScheduler::TaskGroupContext context;
  56. TaskScheduler::spawn(first,last,minStepSize,func,&context);
  57. TaskScheduler::wait();
  58. if (context.cancellingException != nullptr) {
  59. std::rethrow_exception(context.cancellingException);
  60. }
  61. #elif defined(TASKING_TBB)
  62. #if TBB_INTERFACE_VERSION >= 12002
  63. tbb::task_group_context context;
  64. tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) {
  65. func(range<Index>(r.begin(),r.end()));
  66. },context);
  67. if (context.is_group_execution_cancelled())
  68. throw std::runtime_error("task cancelled");
  69. #else
  70. tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) {
  71. func(range<Index>(r.begin(),r.end()));
  72. });
  73. if (tbb::task::self().is_cancelled())
  74. throw std::runtime_error("task cancelled");
  75. #endif
  76. #elif defined(TASKING_PPL)
  77. concurrency::parallel_for(first, last, Index(1) /*minStepSize*/, [&](Index i) {
  78. func(range<Index>(i,i+1));
  79. });
  80. #else
  81. # error "no tasking system enabled"
  82. #endif
  83. }
  84. /* parallel for with range */
  85. template<typename Index, typename Func>
  86. __forceinline void parallel_for( const Index first, const Index last, const Func& func)
  87. {
  88. assert(first <= last);
  89. parallel_for(first,last,(Index)1,func);
  90. }
  91. #if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION > 4001)
  92. template<typename Index, typename Func>
  93. __forceinline void parallel_for_static( const Index N, const Func& func)
  94. {
  95. #if TBB_INTERFACE_VERSION >= 12002
  96. tbb::task_group_context context;
  97. tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
  98. func(i);
  99. },tbb::simple_partitioner(),context);
  100. if (context.is_group_execution_cancelled())
  101. throw std::runtime_error("task cancelled");
  102. #else
  103. tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
  104. func(i);
  105. },tbb::simple_partitioner());
  106. if (tbb::task::self().is_cancelled())
  107. throw std::runtime_error("task cancelled");
  108. #endif
  109. }
  110. typedef tbb::affinity_partitioner affinity_partitioner;
  111. template<typename Index, typename Func>
  112. __forceinline void parallel_for_affinity( const Index N, const Func& func, tbb::affinity_partitioner& ap)
  113. {
  114. #if TBB_INTERFACE_VERSION >= 12002
  115. tbb::task_group_context context;
  116. tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
  117. func(i);
  118. },ap,context);
  119. if (context.is_group_execution_cancelled())
  120. throw std::runtime_error("task cancelled");
  121. #else
  122. tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
  123. func(i);
  124. },ap);
  125. if (tbb::task::self().is_cancelled())
  126. throw std::runtime_error("task cancelled");
  127. #endif
  128. }
  129. #else
  130. template<typename Index, typename Func>
  131. __forceinline void parallel_for_static( const Index N, const Func& func)
  132. {
  133. parallel_for(N,func);
  134. }
  135. struct affinity_partitioner {
  136. };
  137. template<typename Index, typename Func>
  138. __forceinline void parallel_for_affinity( const Index N, const Func& func, affinity_partitioner& ap)
  139. {
  140. parallel_for(N,func);
  141. }
  142. #endif
  143. }