48 #ifdef GETFEM_HAS_OPENMP 
   56 #ifdef GETFEM_HAS_OPENMP 
   57   void parallel_execution(std::function<
void(
void)> lambda,
 
   58                           bool iterate_over_partitions);
 
   68     std::unique_ptr<std::lock_guard<std::recursive_mutex>> plock;
 
   69     static std::recursive_mutex mutex;
 
   76     local_guard(std::recursive_mutex&);
 
   79     std::recursive_mutex& mutex;
 
   80     std::shared_ptr<std::lock_guard<std::recursive_mutex>> plock;
 
   91     local_guard get_lock() 
const;
 
   93     mutable std::recursive_mutex mutex;
 
   96   #define GLOBAL_OMP_GUARD getfem::omp_guard g; GMM_NOPERATION_(abs(&(g) != &(g))); 
  104     inline local_guard get_lock()
 const {
return local_guard();}
 
  106   #define GLOBAL_OMP_GUARD 
  138     struct general_tag{};
 
  143     struct distribute_traits
 
  145       using type = general_tag;
 
  149     struct distribute_traits<std::vector<T>>
 
  151       using type = vector_tag;
 
  155     struct distribute_traits<bool>
 
  157       using type = bool_tag;
 
  160     template<
typename T, 
typename thread_policy, 
typename tag>
 
  161     class omp_distribute_impl;
 
  164     inline auto safe_component(V &v, 
size_type i) -> decltype(v[i]){
 
  165       GMM_ASSERT2(i < v.size(),
 
  166                   i << 
"-th partition is not available. " 
  167                   "Probably on_thread_update " 
  168                   "should have been called first");
 
  172     template <
typename T, 
typename thread_policy>
 
  173     class omp_distribute_impl<T, thread_policy, general_tag> {
 
  175       std::vector<T> thread_values;
 
  176       friend struct all_values_proxy;
 
  178       struct all_values_proxy{
 
  179         omp_distribute_impl& distro;
 
  180         all_values_proxy(omp_distribute_impl& d)
 
  184         void operator = (
const T& x){
 
  185           for(
auto it  = distro.thread_values.begin();
 
  186                    it != distro.thread_values.end(); ++it){
 
  194       template <
class... args>
 
  195        explicit omp_distribute_impl(args&&... value){
 
  196         thread_values.reserve(num_threads());
 
  197         for (
size_type i = 0; i != num_threads(); ++i){
 
  198           thread_values.emplace_back(std::forward<args>(value)...);
 
  203         return operator()(this_thread());
 
  206       operator const T& () 
const {
 
  207         return operator()(this_thread());
 
  211         return operator()(this_thread());
 
  214       const T& thrd_cast()
 const {
 
  215         return operator()(this_thread());
 
  219         return safe_component(thread_values, i);
 
  223         return safe_component(thread_values, i);
 
  226       void on_thread_update() {
 
  227         if (thread_values.size() == num_threads()) 
return;
 
  229         if (thread_values.size() != num_threads()) {
 
  230           thread_values.resize(num_threads());
 
  235         return thread_policy::num_threads();
 
  239         return thread_policy::this_thread();
 
  242       T& operator = (
const T& x){
 
  246         else all_threads() = x;
 
  251       all_values_proxy all_threads(){
 
  252         return all_values_proxy(*
this);
 
  257     template <
typename T,
 
  258               typename thread_policy>
 
  259     class omp_distribute_impl<std::vector<T>, thread_policy, vector_tag>
 
  260       : 
public omp_distribute_impl<std::vector<T>, thread_policy, general_tag>
 
  263       using base = omp_distribute_impl<std::vector<T>, thread_policy, general_tag>;
 
  265       template <
class... args>
 
  266       explicit omp_distribute_impl(args&&... value)
 
  267         : base(std::forward<args>(value)...)
 
  271         return base::thrd_cast()[i];
 
  274         return base::thrd_cast()[i];
 
  277       std::vector<T>& operator = (
const std::vector<T>& x){
 
  278         return base::operator=(x);
 
  285     template <
typename thread_policy>
 
  286     class omp_distribute_impl<bool, thread_policy, bool_tag>
 
  287       : 
public omp_distribute_impl<int, thread_policy, general_tag>
 
  290       using base = omp_distribute_impl<int, thread_policy, general_tag>;
 
  292       template <
class... Args>
 
  293       explicit omp_distribute_impl(Args&&... value)
 
  294         : base(std::forward<Args>(value)...)
 
  297       operator bool ()
 const {
 
  298         return base::operator 
const int&();
 
  301       bool operator = (
const bool& x){
 
  302         return base::operator=(x);
 
  308   template<
typename T, 
typename thread_policy>
 
  309   using od_base = 
typename detail::omp_distribute_impl
 
  310     <T, thread_policy, 
typename detail::distribute_traits<T>::type>;
 
  328     using base = od_base<T, thread_policy>;
 
  330     template <
class... args>
 
  332       : base(std::forward<args>(value)...)
 
  335     auto operator = (
const T& x) -> decltype(std::declval<base>() = x){
 
  336       return base::operator=(x);
 
  344   #ifdef GETFEM_HAS_OPENMP 
  345     #define THREAD_SAFE_STATIC thread_local 
  347     #define THREAD_SAFE_STATIC static 
  370                        std::set<size_type>::const_iterator it);
 
  373     std::set<size_type>::const_iterator it;
 
  376   enum class thread_behaviour {true_threads, partition_threads};
 
  411     void check_threads();
 
  415     void rewind_partitions();
 
  418     friend void parallel_execution(std::function<
void(
void)> lambda, 
bool iterate_over_partitions);
 
  427     void update_partitions();
 
  431     std::atomic<size_type> nb_user_threads;
 
  432     thread_behaviour behaviour = thread_behaviour::partition_threads;
 
  433     std::atomic<bool> partitions_updated{
false};
 
  435     bool partitions_set_by_user = 
false;
 
  446     std::unique_ptr<standard_locale> plocale;
 
  447     std::unique_ptr<thread_exception> pexception;
 
  451     void run_lambda(std::function<
void(
void)> lambda);
 
  456     #define pragma_op(arg) _Pragma("arg")
 
  458     #define pragma_op(arg) __pragma(arg) 
  467   #ifdef GETFEM_HAS_OPENMP 
  468     #define GETFEM_OMP_PARALLEL(body) getfem::parallel_execution([&](){body;}, true); 
  471     #define GETFEM_OMP_PARALLEL_NO_PARTITION(body) getfem::parallel_execution([&](){body;}, false); 
  474     #define GETFEM_OMP_FOR(init, check, increment, body) {\ 
  475       auto boilerplate = getfem::parallel_boilerplate{};  \ 
  476       pragma_op(omp parallel for)                         \ 
  477       for (init; check; increment){                       \ 
  478         boilerplate.run_lambda([&](){body;});              \ 
  483     #define GETFEM_OMP_PARALLEL(body) body 
  484     #define GETFEM_OMP_PARALLEL_NO_PARTITION(body) body; 
  485     #define GETFEM_OMP_FOR(init, check, increment, body)\ 
  486       for (init; check; increment) {                    \ 
defines and typedefs for namespace bgeot
Use this template class for any object you want to distribute to open_MP threads.
Encapsulates open_mp-related initialization and de-initialization.
Iterator that runs over partitions on the current thread and sets the global (but thread-specific) pa...
A singleton that Manages partitions on individual threads.
partition_iterator begin()
beginning of the partitions for the current thread
size_type get_current_partition() const
active partition on the thread.
size_type get_nb_partitions() const
number of partitions or threads, depending on thread policy
partition_iterator end()
end of the partitions for the current thread
void set_nb_partitions(size_type)
for thread_behaviour::partition_threads set the total number of partitions.
void set_behaviour(thread_behaviour)
Sets the behaviour for the full program: either partitioning parallel loops according to the number o...
Identical to gmm::standard_locale, but does not change std::locale in multi-threaded sections of the ...
Allows to re-throw exceptions, generated in OpemMP parallel section.
size_t size_type
used as the common size type in the library
GEneric Tool for Finite Element Methods.
bool not_multithreaded()
is the program is running on a single thread
size_type max_concurrency()
Maximum number of threads that can run concurrently.
bool me_is_multithreaded_now()
is the program running in the parallel section
void set_num_threads(int n)
set maximum number of OpenMP threads
Thread policy, regulated by partition_master (can be true thread- or partition-based)
Thread policy, where partitioning is based on true threads.