GetFEM++  5.3
getfem_omp.cc
1 /*===========================================================================
2 
3  Copyright (C) 2012-2017 Andriy Andreykiv.
4 
5  This file is a part of GetFEM++
6 
7  GetFEM++ is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program; if not, write to the Free Software Foundation,
18  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20 ===========================================================================*/
21 
22 #include "getfem/getfem_omp.h"
23 #include "getfem/getfem_mesh.h"
24 
25 namespace getfem{
26 
27 #ifdef GETFEM_HAVE_OPENMP
28 
29  boost::recursive_mutex omp_guard::boost_mutex;
30 
31  omp_guard::omp_guard()
32  : boost::lock_guard<boost::recursive_mutex>(boost_mutex)
33  {}
34 
35  local_guard::local_guard(boost::recursive_mutex& m) :
36  mutex_(m),
37  plock_(new boost::lock_guard<boost::recursive_mutex>(m))
38  { }
39 
40  local_guard::local_guard(const local_guard& guard)
41  : mutex_(guard.mutex_), plock_(guard.plock_)
42  { }
43 
44  lock_factory::lock_factory() : mutex_() {}
45  local_guard lock_factory::get_lock() const
46  {
47  return local_guard(mutex_);
48  }
49 #endif
50 
51  omp_distribute<bool> open_mp_is_running_properly::answer = false;
52  open_mp_is_running_properly::open_mp_is_running_properly()
53  {answer.all_threads()=true;}
54  open_mp_is_running_properly::~open_mp_is_running_properly()
55  {answer.all_threads()=false;}
56  bool open_mp_is_running_properly::is_it(){return answer;}
57 
58  region_partition::region_partition(const region_partition& rp) :
59  pparent_mesh(rp.pparent_mesh),
60  original_region(rp.original_region),
61  partitions(rp.partitions) { }
62 
63  void region_partition::operator=(const region_partition& rp)
64  {
65  partitions.clear();
66 
67  if (!rp.pparent_mesh) return;
68  pparent_mesh->copy_from(*rp.pparent_mesh);
69  original_region = rp.original_region;
70  partitions.resize(rp.partitions.size());
71  gmm::copy(rp.partitions,partitions);
72  }
73 
74 
75  region_partition::region_partition(mesh* pm, size_type id) :
76  pparent_mesh(pm),original_region(0),
77  partitions(num_threads())
78  {
79  scalar_type time = gmm::uclock_sec();
80  // in case of serial Getfem nothing to partition
81  if (num_threads()==1) {partitions[0]=id; return;}
82 
83  //in case mesh is not provided, also don't do anything
84  if (!pm) return;
85 
86  if (id == size_type(-1)) {
87  original_region.reset(new mesh_region(pm->convex_index()));
88  original_region->set_parent_mesh(pm);
89  } else{
90  GMM_ASSERT1(pm->has_region(id),"Improper region number");
91  original_region.reset(new mesh_region(pm->region(id)));
92  }
93  if (me_is_multithreaded_now())
94  GMM_WARNING0("building partitions inside parallel region");
95 
96  omp_guard scoped_lock;
97  GMM_NOPERATION(scoped_lock);
98  size_type Nelems = original_region->size();
99  size_type psize = static_cast<size_type>
100  (std::ceil(static_cast<scalar_type >(Nelems)/
101  static_cast<scalar_type >(num_threads())));
102  mr_visitor mr(*original_region);
103  for(size_type thread = 0; thread<num_threads();thread++)
104  {
105  partitions[thread] =
106  getfem::mesh_region::free_region_id(*(original_region->get_parent_mesh()));
107  mesh_region partition;
108  for(size_type i=thread*psize;i<(thread+1)*psize && !mr.finished();i++,++mr)
109  {
110  if (mr.is_face()) partition.add(mr.cv(),mr.f());
111  else partition.add(mr.cv());
112  }
113  pparent_mesh->region(partitions[thread]) = partition;
114  }
115  GMM_TRACE2("Partitioning time: "<<gmm::uclock_sec()-time<<" s.");
116  }
117 
118  size_type region_partition::
119  thread_local_partition() const {
120  if (pparent_mesh==0 && num_threads() >1 ){
121  GMM_WARNING1("partition is empty and cannot be used \
122  this means that the brick that created it should partition \
123  its domain by himself");
124  return -10;
125  }
126  return partitions[this_thread()];
127  }
128 
129  void omp_distribute<bool>::all_values_proxy::operator=(const bool& x)
130  {
131  for(std::vector<BOOL>::iterator it=distro.thread_values.begin();
132  it!=distro.thread_values.end();it++) *it=x;
133 
134  }
135 
136  thread_exception::thread_exception(): exceptions_(num_threads(), nullptr)
137  { }
138 
140 
141  std::vector<std::exception_ptr> thread_exception::caughtExceptions() const
142  {
143  std::vector<std::exception_ptr> exceptions;
144  for (auto &&pException : exceptions_)
145  {
146  if (pException != nullptr) exceptions.push_back(pException);
147  }
148  return exceptions;
149  }
150 
151  void thread_exception::rethrow()
152  {
153  for (auto &&pException : exceptions_)
154  {
155  if (pException != nullptr) std::rethrow_exception(pException);
156  }
157  }
158 
159  void thread_exception::captureException()
160  {
161  exceptions_[this_thread()] = std::current_exception();
162  }
163 
164 }
Define a getfem::getfem_mesh object.
Tools for multithreaded, OpenMP and Boost based parallelization.
static size_type free_region_id(const getfem::mesh &m)
Extract the next region number that does not yet exists in the mesh.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
void copy_from(const mesh &m)
Clone a mesh.
Definition: getfem_mesh.cc:446
GEneric Tool for Finite Element Methods.
~thread_exception()
re-throws the first captured exception
Definition: getfem_omp.cc:139
std::vector< std::exception_ptr > caughtExceptions() const
vector of pointers to caught exceptions
Definition: getfem_omp.cc:141