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