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 // no op preparation/accumulation
129 const auto & no_op = [](const size_t /*n/t*/){};
130 // two-parameter wrapper ignoring thread id
131 const auto & wrapper = [&func](Index i,size_t /*t*/){ func(i); };
132 return parallel_for(loop_size,no_op,wrapper,no_op,min_parallel);
133}
134
135template<
136 typename Index,
137 typename PreFunctionType,
138 typename FunctionType,
139 typename AccumFunctionType>
140inline bool igl::parallel_for(
141 const Index loop_size,
142 const PreFunctionType & prep_func,
143 const FunctionType & func,
144 const AccumFunctionType & accum_func,
145 const size_t min_parallel)
146{
147 assert(loop_size>=0);
148 if(loop_size==0) return false;
149 // Estimate number of threads in the pool
150 // http://ideone.com/Z7zldb
151#ifdef IGL_PARALLEL_FOR_FORCE_SERIAL
152 const size_t nthreads = 1;
153#else
154 const size_t nthreads = igl::default_num_threads();
155#endif
156 if(loop_size<min_parallel || nthreads<=1)
157 {
158 // serial
159 prep_func(1);
160 for(Index i = 0;i<loop_size;i++) func(i,0);
161 accum_func(0);
162 return false;
163 }else
164 {
165 // Size of a slice for the range functions
166 Index slice =
167 std::max(
168 (Index)std::round((loop_size+1)/static_cast<double>(nthreads)),(Index)1);
169
170 // [Helper] Inner loop
171 const auto & range = [&func](const Index k1, const Index k2, const size_t t)
172 {
173 for(Index k = k1; k < k2; k++) func(k,t);
174 };
175 prep_func(nthreads);
176 // Create pool and launch jobs
177 std::vector<std::thread> pool;
178 pool.reserve(nthreads);
179 // Inner range extents
180 Index i1 = 0;
181 Index i2 = std::min(0 + slice, loop_size);
182 {
183 size_t t = 0;
184 for (; t+1 < nthreads && i1 < loop_size; ++t)
185 {
186 pool.emplace_back(range, i1, i2, t);
187 i1 = i2;
188 i2 = std::min(i2 + slice, loop_size);
189 }
190 if (i1 < loop_size)
191 {
192 pool.emplace_back(range, i1, loop_size, t);
193 }
194 }
195 // Wait for jobs to finish
196 for (std::thread &t : pool) if (t.joinable()) t.join();
197 // Accumulate across threads
198 for(size_t t = 0;t<nthreads;t++)
199 {
200 accum_func(t);
201 }
202 return true;
203 }
204}
205
206//#ifndef IGL_STATIC_LIBRARY
207//#include "parallel_for.cpp"
208//#endif
209#endif
Definition AABB.h:18
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.