libigl v2.5.0
Loading...
Searching...
No Matches
parallel_for.h
Go to the documentation of this file.
1// This file is part of libigl, a simple c++ geometry processing library.
2//
3// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
4//
5// This Source Code Form is subject to the terms of the Mozilla Public License
6// v. 2.0. If a copy of the MPL was not distributed with this file, You can
7// obtain one at http://mozilla.org/MPL/2.0/.
8#ifndef IGL_PARALLEL_FOR_H
9#define IGL_PARALLEL_FOR_H
10#include "igl_inline.h"
11#include <functional>
12
13//#warning "Defining IGL_PARALLEL_FOR_FORCE_SERIAL"
14//#define IGL_PARALLEL_FOR_FORCE_SERIAL
15
16namespace igl
17{
60 template<typename Index, typename FunctionType >
61 inline bool parallel_for(
62 const Index loop_size,
63 const FunctionType & func,
64 const size_t min_parallel=0);
98 template<
99 typename Index,
100 typename PrepFunctionType,
101 typename FunctionType,
102 typename AccumFunctionType
103 >
104 inline bool parallel_for(
105 const Index loop_size,
106 const PrepFunctionType & prep_func,
107 const FunctionType & func,
108 const AccumFunctionType & accum_func,
109 const size_t min_parallel=0);
110}
111
112// Implementation
113
114#include "default_num_threads.h"
115
116#include <cmath>
117#include <cassert>
118#include <thread>
119#include <vector>
120#include <algorithm>
121
122template<typename Index, typename FunctionType >
124 const Index loop_size,
125 const FunctionType & func,
126 const size_t min_parallel)
127{
128 using namespace std;
129 // no op preparation/accumulation
130 const auto & no_op = [](const size_t /*n/t*/){};
131 // two-parameter wrapper ignoring thread id
132 const auto & wrapper = [&func](Index i,size_t /*t*/){ func(i); };
133 return parallel_for(loop_size,no_op,wrapper,no_op,min_parallel);
134}
135
136template<
137 typename Index,
138 typename PreFunctionType,
139 typename FunctionType,
140 typename AccumFunctionType>
141inline bool igl::parallel_for(
142 const Index loop_size,
143 const PreFunctionType & prep_func,
144 const FunctionType & func,
145 const AccumFunctionType & accum_func,
146 const size_t min_parallel)
147{
148 assert(loop_size>=0);
149 if(loop_size==0) return false;
150 // Estimate number of threads in the pool
151 // http://ideone.com/Z7zldb
152#ifdef IGL_PARALLEL_FOR_FORCE_SERIAL
153 const size_t nthreads = 1;
154#else
155 const size_t nthreads = igl::default_num_threads();
156#endif
157 if(loop_size<min_parallel || nthreads<=1)
158 {
159 // serial
160 prep_func(1);
161 for(Index i = 0;i<loop_size;i++) func(i,0);
162 accum_func(0);
163 return false;
164 }else
165 {
166 // Size of a slice for the range functions
167 Index slice =
168 std::max(
169 (Index)std::round((loop_size+1)/static_cast<double>(nthreads)),(Index)1);
170
171 // [Helper] Inner loop
172 const auto & range = [&func](const Index k1, const Index k2, const size_t t)
173 {
174 for(Index k = k1; k < k2; k++) func(k,t);
175 };
176 prep_func(nthreads);
177 // Create pool and launch jobs
178 std::vector<std::thread> pool;
179 pool.reserve(nthreads);
180 // Inner range extents
181 Index i1 = 0;
182 Index i2 = std::min(0 + slice, loop_size);
183 {
184 size_t t = 0;
185 for (; t+1 < nthreads && i1 < loop_size; ++t)
186 {
187 pool.emplace_back(range, i1, i2, t);
188 i1 = i2;
189 i2 = std::min(i2 + slice, loop_size);
190 }
191 if (i1 < loop_size)
192 {
193 pool.emplace_back(range, i1, loop_size, t);
194 }
195 }
196 // Wait for jobs to finish
197 for (std::thread &t : pool) if (t.joinable()) t.join();
198 // Accumulate across threads
199 for(size_t t = 0;t<nthreads;t++)
200 {
201 accum_func(t);
202 }
203 return true;
204 }
205}
206
207//#ifndef IGL_STATIC_LIBRARY
208//#include "parallel_for.cpp"
209//#endif
210#endif
Definition AABB.h:17
bool parallel_for(const Index loop_size, const FunctionType &func, const size_t min_parallel=0)
Functional implementation of a basic, open-mp style, parallel for loop.
Definition parallel_for.h:123
void slice(const Eigen::SparseMatrix< TX > &X, const Eigen::DenseBase< DerivedR > &R, const Eigen::DenseBase< DerivedC > &C, Eigen::SparseMatrix< TY > &Y)
Act like the matlab X(row_indices,col_indices) operator, where row_indices, col_indices are non-negat...
unsigned int default_num_threads(unsigned int force_num_threads=0)
Returns the default number of threads used in libigl.