OWL
Loading...
Searching...
No Matches
parallel_for.h
1// ======================================================================== //
2// Copyright 2018-2019 Ingo Wald //
3// //
4// Licensed under the Apache License, Version 2.0 (the "License"); //
5// you may not use this file except in compliance with the License. //
6// You may obtain a copy of the License at //
7// //
8// http://www.apache.org/licenses/LICENSE-2.0 //
9// //
10// Unless required by applicable law or agreed to in writing, software //
11// distributed under the License is distributed on an "AS IS" BASIS, //
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
13// See the License for the specific language governing permissions and //
14// limitations under the License. //
15// ======================================================================== //
16
17#pragma once
18
19#include <owl/common/owl-common.h>
20// std
21#include <mutex>
22
23#ifdef OWL_DISABLE_TBB
24# undef OWL_HAVE_TBB
25#endif
26
27// tbb
28#if OWL_HAVE_TBB
29#include <tbb/parallel_for.h>
30#include <tbb/task_arena.h>
31#define OWL_HAVE_PARALLEL_FOR 1
32#endif
33
34namespace owl {
35 namespace common {
36
37 template<typename INDEX_T, typename TASK_T>
38 inline void serial_for(INDEX_T nTasks, TASK_T&& taskFunction)
39 {
40 for (INDEX_T taskIndex = 0; taskIndex < nTasks; ++taskIndex) {
41 taskFunction(taskIndex);
42 }
43 }
44
45#if OWL_HAVE_TBB
46 template<typename INDEX_T, typename TASK_T>
47 inline void parallel_for(INDEX_T nTasks, TASK_T&& taskFunction, size_t blockSize=1)
48 {
49 if (nTasks == 0) return;
50 if (nTasks == 1)
51 taskFunction(size_t(0));
52 else if (blockSize==1) {
53 tbb::parallel_for(INDEX_T(0), nTasks, std::forward<TASK_T>(taskFunction));
54 } else {
55 const size_t numBlocks = (nTasks+blockSize-1)/blockSize;
56 tbb::parallel_for((size_t)0, numBlocks, [&](size_t blockIdx){
57 size_t begin = blockIdx*blockSize;
58 size_t end = std::min(begin+blockSize,size_t(nTasks));
59 for (size_t i=begin;i<end;i++)
60 taskFunction(INDEX_T(i));
61 });
62 }
63 }
64#else
65#ifndef OWL_DISABLE_TBB
66// # pragma message("warning: TBB not available, will replace all parallel_for's with serial_for's")
67#endif
68 template<typename INDEX_T, typename TASK_T>
69 inline void parallel_for(INDEX_T nTasks, TASK_T&& taskFunction, size_t blockSize=1)
70 { serial_for(nTasks,taskFunction); }
71#endif
72
73 // template<typename TASK_T>
74 // void parallel_for_blocked(size_t numTasks, size_t blockSize,
75 // TASK_T &&taskFunction)
76 // {
77 // for (size_t begin=0; begin < numTasks; begin += blockSize)
78 // taskFunction(begin,std::min(begin+blockSize,numTasks));
79 // }
80
81 template<typename TASK_T>
82 void serial_for_blocked(size_t begin, size_t end, size_t blockSize,
83 TASK_T &&taskFunction)
84 {
85 for (size_t block_begin=begin; block_begin < end; block_begin += blockSize)
86 taskFunction(block_begin,std::min(block_begin+blockSize,end));
87 }
88
89 template<typename TASK_T>
90 void parallel_for_blocked(size_t begin, size_t end, int blockSize,
91 const TASK_T &taskFunction)
92 {
93#if 0
94 serial_for_blocked(begin,end,blockSize,taskFunction);
95#else
96 const size_t numTasks = end-begin;
97 const size_t numBlocks = (numTasks+blockSize-1)/blockSize;
98 parallel_for(numBlocks,[&](size_t blockID){
99 size_t block_begin = begin+blockID*blockSize;
100 taskFunction(block_begin,std::min(block_begin+blockSize,end));
101 });
102#endif
103 }
104
105 template<typename TASK_T>
106 void parallel_for_blocked(int begin, int end, int blockSize,
107 const TASK_T& taskFunction)
108 {
109#if 0
110 serial_for_blocked(begin, end, blockSize, taskFunction);
111#else
112 const int numTasks = end - begin;
113 const int numBlocks = (numTasks + blockSize - 1) / blockSize;
114 parallel_for(numBlocks, [&](int blockID) {
115 int block_begin = begin + blockID * blockSize;
116 taskFunction(block_begin, std::min(block_begin + blockSize, end));
117 });
118#endif
119 }
120
121 } // ::owl::common
122} // ::owl