54 #ifdef GETFEM_HAVE_OPENMP 56 #include <boost/thread.hpp> 57 #include <boost/shared_ptr.hpp> 58 #include <boost/make_shared.hpp> 69 #ifdef GETFEM_HAVE_OPENMP 72 class omp_guard:
public boost::lock_guard<boost::recursive_mutex>
77 static boost::recursive_mutex boost_mutex;
84 local_guard(boost::recursive_mutex&);
85 local_guard(
const local_guard&);
88 boost::recursive_mutex& mutex_;
89 boost::shared_ptr<boost::lock_guard<boost::recursive_mutex>> plock_;
101 local_guard get_lock()
const;
103 mutable boost::recursive_mutex mutex_;
113 inline local_guard get_lock()
const {
return local_guard();}
118 #ifdef GETFEM_HAVE_OPENMP 120 inline size_t num_threads(){
return omp_get_max_threads();}
123 inline void set_num_threads(
int n){omp_set_num_threads(n);}
126 inline size_type this_thread() {
return omp_get_thread_num();}
128 inline bool me_is_multithreaded_now(){
return static_cast<bool>(omp_in_parallel());}
132 inline void set_num_threads(
int ) { }
134 inline bool me_is_multithreaded_now(){
return false;}
147 std::vector<T> thread_values;
148 friend struct all_values_proxy;
149 struct all_values_proxy{
152 void operator=(
const T& x){
153 for(
typename std::vector<T>::iterator it=distro.thread_values.begin();
154 it!=distro.thread_values.end();it++) *it=x;
159 template <
class... Args>
161 for (
size_type i = 0; i < num_threads(); ++i) thread_values.emplace_back(value...);
163 operator T& (){
return thread_values[this_thread()];}
164 operator const T& ()
const {
return thread_values[this_thread()];}
165 T& thrd_cast(){
return thread_values[this_thread()];}
166 const T& thrd_cast()
const {
return thread_values[this_thread()];}
168 return thread_values[i];
171 return thread_values[i];
173 T& operator = (
const T& x){
174 return (thread_values[this_thread()]=x);
177 all_values_proxy all_threads(){
return all_values_proxy(*
this);}
183 std::vector<std::vector<T> > thread_values;
184 friend struct all_values_proxy;
185 struct all_values_proxy{
188 void operator=(
const T& x){
189 for(
typename std::vector<T>::iterator it=distro.thread_values.begin();
190 it!=distro.thread_values.end();it++) *it=x;
195 typedef std::vector<T> VEC;
198 thread_values(num_threads(), std::vector<T>(n,value)){}
199 operator VEC& (){
return thread_values[this_thread()];}
200 operator const VEC& ()
const 201 {
return thread_values[this_thread()];}
202 VEC& operator()(
size_type i) {
return thread_values[i];}
203 const VEC& operator()(
size_type i)
const {
return thread_values[i];}
204 VEC& thrd_cast(){
return thread_values[this_thread()];}
205 const VEC& thrd_cast()
const 206 {
return thread_values[this_thread()];}
208 {
return thread_values[this_thread()][i];}
210 {
return thread_values[this_thread()][i];}
211 T& operator = (
const T& value) {
212 return (thread_values[this_thread()]=value);
214 all_values_proxy all_threads(){
return all_values_proxy(*
this);}
222 std::vector<BOOL> thread_values;
223 friend struct all_values_proxy;
224 struct all_values_proxy{
227 void operator=(
const bool& x);
235 thread_values(num_threads(),value) {}
236 operator BOOL& (){
return thread_values[this_thread()];}
237 operator const BOOL& ()
const {
return thread_values[this_thread()];}
238 BOOL& thrd_cast(){
return thread_values[this_thread()];}
239 const BOOL& thrd_cast()
const {
return thread_values[this_thread()];}
241 return thread_values[i];
243 const BOOL& operator()(
size_type i)
const {
244 return thread_values[i];
246 BOOL& operator = (
const BOOL& x){
247 return (thread_values[this_thread()]=x);
249 all_values_proxy all_threads(){
return all_values_proxy(*
this);}
259 #ifdef GETFEM_HAVE_OPENMP 260 #define DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(Type,Var,initial) \ 261 static boost::thread_specific_ptr<Type> ptr_##Var; \ 262 if(!ptr_##Var.get()) {ptr_##Var.reset(new Type(initial));} \ 263 Type& Var=*ptr_##Var; 265 #define DEFINE_STATIC_THREAD_LOCAL(Type,Var) \ 266 static boost::thread_specific_ptr<Type> ptr_##Var; \ 267 if(!ptr_##Var.get()) {ptr_##Var.reset(new Type());} \ 268 Type& Var=*ptr_##Var; 270 #define DEFINE_STATIC_THREAD_LOCAL_CONSTRUCTED(Type, Var, ...) \ 271 static boost::thread_specific_ptr<Type> ptr_##Var; \ 272 if(!ptr_##Var.get()) {ptr_##Var.reset(new Type(__VA_ARGS__));} \ 273 Type& Var=*ptr_##Var; 276 #define DEFINE_STATIC_THREAD_LOCAL_INITIALIZED(Type,Var,initial) \ 277 static Type Var(initial); 279 #define DEFINE_STATIC_THREAD_LOCAL(Type,Var) \ 282 #define DEFINE_STATIC_THREAD_LOCAL_CONSTRUCTED(Type, Var, ...) \ 283 static Type Var(__VA_ARGS__); 287 class open_mp_is_running_properly{
291 open_mp_is_running_properly();
292 ~open_mp_is_running_properly();
296 #if defined _WIN32 && !defined (__GNUC__) 298 template<
class LOOP_BODY>
300 const LOOP_BODY& loop_body){
301 _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
303 open_mp_is_running_properly check;
304 #pragma omp parallel default(shared) 306 _setmbcp(_MB_CP_ANSI);
307 #pragma omp for schedule(static) 308 for(
int i=begin;i<end;i++) loop_body(i);
310 _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
314 template<
class LOOP_BODY>
316 int begin,
int end,
const LOOP_BODY& loop_body){
318 open_mp_is_running_properly check;
319 #pragma omp parallel default(shared) 321 #pragma omp for schedule(static) 322 for(
int i=begin;i<end;i++) loop_body(i);
328 #define OPEN_MP_FOR(begin,end,loop_counter,loop_body) \ 329 getfem::open_mp_for(begin,end,loop_body(loop_counter)); 335 std::shared_ptr<mesh_region> original_region;
336 mutable std::vector<size_type> partitions;
341 size_type thread_local_partition()
const;
367 template <
typename Function,
typename... Parameters>
368 void run(Function f, Parameters... params)
370 #ifdef GETFEM_HAVE_OPENMP 371 try { f(params...); }
catch (...) { captureException(); }
378 std::vector<std::exception_ptr> caughtExceptions()
const;
382 void captureException();
384 std::vector<std::exception_ptr> exceptions_;
multi-threaded distribution of a single vector or a matrix.
basic setup for gmm (includes, typedefs etc.)
use this template class for any object you want to distribute to open_MP threads. ...
specialization for bool, to circumvent the shortcommings of standards library specialization for std:...
Describe a mesh (collection of convexes (elements) and points).
size_t size_type
used as the common size type in the library
this is the above solutions for linux, but it still needs to be tested.
GEneric Tool for Finite Element Methods.
void open_mp_for(int begin, int end, const LOOP_BODY &loop_body)
parallelization function for a for loop
void run(Function f, Parameters...params)
Run function f in parallel part to capture it's exceptions.
Allows to re-throw exceptions, generated in OpemMP parallel section.
used to partition a mesh region so that each partition can be used on a different thread...
defines and typedefs for namespace bgeot