getfem-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Getfem-commits] r5090 - in /trunk/getfem/src: getfem/getfem_copyable_pt


From: andriy . andreykiv
Subject: [Getfem-commits] r5090 - in /trunk/getfem/src: getfem/getfem_copyable_ptr.h getfem_generic_assembly.cc
Date: Tue, 06 Oct 2015 14:50:56 -0000

Author: andrico
Date: Tue Oct  6 16:50:55 2015
New Revision: 5090

URL: http://svn.gna.org/viewcvs/getfem?rev=5090&view=rev
Log:
"Thread-safing" ga_predef_function class. Making the cached members distributed.
Small stylistic changes with respect to encapsulation

Added:
    trunk/getfem/src/getfem/getfem_copyable_ptr.h   (with props)
Modified:
    trunk/getfem/src/getfem_generic_assembly.cc

Added: trunk/getfem/src/getfem/getfem_copyable_ptr.h
URL: 
http://svn.gna.org/viewcvs/getfem/trunk/getfem/src/getfem/getfem_copyable_ptr.h?rev=5090&view=auto
==============================================================================
--- trunk/getfem/src/getfem/getfem_copyable_ptr.h       (added)
+++ trunk/getfem/src/getfem/getfem_copyable_ptr.h       Tue Oct  6 16:50:55 2015
@@ -0,0 +1,73 @@
+/* -*- c++ -*- (enables emacs c++ mode) */
+/*===========================================================================
+
+ Copyright (C) 2012-2015 Andriy Andreykiv
+
+ This file is a part of GetFEM++
+
+ GetFEM++  is  free software;  you  can  redistribute  it  and/or modify it
+ under  the  terms  of the  GNU  Lesser General Public License as published
+ by  the  Free Software Foundation;  either version 3 of the License,  or
+ (at your option) any later version along with the GCC Runtime Library
+ Exception either version 3.1 or (at your option) any later version.
+ This program  is  distributed  in  the  hope  that it will be useful,  but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License and GCC Runtime Library Exception for more details.
+ You  should  have received a copy of the GNU Lesser General Public License
+ along  with  this program;  if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ As a special exception, you  may use  this file  as it is a part of a free
+ software  library  without  restriction.  Specifically,  if   other  files
+ instantiate  templates  or  use macros or inline functions from this file,
+ or  you compile this  file  and  link  it  with other files  to produce an
+ executable, this file  does  not  by itself cause the resulting executable
+ to be covered  by the GNU Lesser General Public License.  This   exception
+ does not  however  invalidate  any  other  reasons why the executable file
+ might be covered by the GNU Lesser General Public License.
+
+===========================================================================*/
+/address@hidden getfem_copyable_ptr.h
address@hidden  Andriy Andreykiv <address@hidden>
address@hidden May 6th, 2015.
address@hidden A smart pointer that copies the value it points to on copy 
operations
+*/
+#pragma once
+
+#include <memory>
+
+namespace getfem {
+
+/**
+  A wrapper around a unique_ptr that clones the value on copy
+*/
+template<class T> class copyable_ptr{
+  std::unique_ptr<T> p_ = nullptr;
+public:
+  copyable_ptr() = default;
+
+  copyable_ptr(std::unique_ptr<T> p) : p_(std::move(p)) {}
+
+  copyable_ptr(const copyable_ptr<T> &x) : p_(x.p_ ? 
std::make_unique<T>(*x.p_) : nullptr)  {}
+
+  copyable_ptr(copyable_ptr<T> &&x) : p_(std::move(*x.p_))  {}
+
+  copyable_ptr<T> &operator=(const copyable_ptr<T> &x){
+    if (x.p_) p_ = std::make_unique<T>(*x.p_);
+    return *this;
+  }
+
+  copyable_ptr<T> &operator=(copyable_ptr<T> &&x){
+    p_ = std::move(x.p_);
+    return *this;
+  }
+
+  operator bool() const {return p_.operator bool();}
+
+  T& operator*() const {return *p_;}
+
+  T& operator->() const {return *p_;}
+};
+
+} // namespace getfem

Propchange: trunk/getfem/src/getfem/getfem_copyable_ptr.h
------------------------------------------------------------------------------
    svn:keywords = Id URL Header

Modified: trunk/getfem/src/getfem_generic_assembly.cc
URL: 
http://svn.gna.org/viewcvs/getfem/trunk/getfem/src/getfem_generic_assembly.cc?rev=5090&r1=5089&r2=5090&view=diff
==============================================================================
--- trunk/getfem/src/getfem_generic_assembly.cc (original)
+++ trunk/getfem/src/getfem_generic_assembly.cc Tue Oct  6 16:50:55 2015
@@ -27,6 +27,7 @@
 #include "getfem/dal_singleton.h"
 #include "getfem/bgeot_rtree.h"
 #include "getfem/bgeot_geotrans_inv.h"
+#include "getfem/getfem_copyable_ptr.h"
 
 /**
   Providing for special Math functions unavailable on Intel or MSVS C++
@@ -1975,46 +1976,53 @@
                            const std::string &varname,
                            const std::string &interpolatename);
 
-
-  struct ga_predef_function {
-    size_type ftype; // 0 : C++ function with C++ derivative(s)
+  class ga_predef_function {
+    size_type ftype_; // 0 : C++ function with C++ derivative(s)
                      // 1 : function defined by an string expression.
 
-    size_type dtype; // 0 : no derivative(s)
+    size_type dtype_; // 0 : no derivative(s)
                      // 1 : derivative(s) given by C++ functions
                      // 2 : derivatives(s) given by string expression(s)
                      // 3 : derivatives(s) to be symbolically computed.
-    size_type nbargs;         // One or two arguments
-    pscalar_func_onearg f1;   // Function pointer for a one argument function
-    pscalar_func_twoargs f2;  // Function pointer for a two arguments function
-    std::string expr;
-    std::string derivative1, derivative2;
-    mutable base_vector t,u;
-    mutable ga_workspace workspace;
-    mutable ga_instruction_set *gis;
-
+    size_type nbargs_;         // One or two arguments
+    pscalar_func_onearg f1_;   // Function pointer for a one argument function
+    pscalar_func_twoargs f2_;  // Function pointer for a two arguments function
+    std::string expr_;
+    std::string derivative1_, derivative2_;
+    mutable omp_distribute<base_vector> t, u;
+    mutable omp_distribute<ga_workspace> workspace;
+    copyable_ptr<omp_distribute<ga_instruction_set>> gis = nullptr;
+
+    friend void ga_define_function(const std::string name, size_type nbargs,
+                                   const std::string expr, const std::string 
der1,
+                                   const std::string der2);
+    friend void ga_define_function(const std::string name, pscalar_func_onearg 
f,
+                                   const std::string &der);
+    friend void ga_define_function(const std::string name, 
pscalar_func_twoargs f,
+                                   const std::string &der1, const std::string 
&der2);
+  public:
     scalar_type operator()(scalar_type t_, scalar_type u_ = 0.) const {
-      switch(ftype) {
+      switch(ftype_) {
       case 0:
-        if (nbargs == 2)
-          return (*f2)(t_, u_);
+        if (nbargs_ == 2)
+          return (*f2_)(t_, u_);
         else
-          return (*f1)(t_);
+          return (*f1_)(t_);
         break;
       case 1:
         t[0] = t_; u[0] = u_;
-        workspace.assembled_potential() = scalar_type(0);
-        ga_function_exec(*gis);
-        return workspace.assembled_potential();
+        workspace.thrd_cast().assembled_potential() = scalar_type(0);
+        ga_function_exec((*gis).thrd_cast());
+        return workspace.thrd_cast().assembled_potential();
         break;
       }
       return 0.;
     }
 
     bool is_affine(const std::string &varname) const {
-      if (ftype == 1) {
-        for (size_type i = 0; i < workspace.nb_trees(); ++i) {
-          ga_workspace::tree_description &td = workspace.tree_info(i);
+      if (ftype_ == 1) {
+        for (size_type i = 0; i < workspace.thrd_cast().nb_trees(); ++i) {
+          ga_workspace::tree_description &td = 
workspace.thrd_cast().tree_info(i);
           if (!(ga_is_affine(*(td.ptree), workspace, varname, "")))
             return false;
         }
@@ -2023,21 +2031,28 @@
       return false;
     }
 
-    ga_predef_function(void) : expr(""), derivative1(""), derivative2(""), 
gis(0) {}
+    size_type ftype() const {return ftype_;}
+    size_type dtype() const {return dtype_;}
+    size_type nbargs() const {return nbargs_;}
+    const std::string &derivative1() const {return derivative1_;}
+    const std::string &derivative2() const {return derivative2_;}
+    const std::string &expr() const {return expr_;}
+    pscalar_func_onearg f1() const {return f1_;}
+    pscalar_func_twoargs f2() const {return f2_;}
+
+    ga_predef_function(void) : expr_(""), derivative1_(""), derivative2_(""), 
gis(nullptr) {}
     ga_predef_function(pscalar_func_onearg f, size_type dtype_ = 0,
                        const std::string &der = "")
-      : ftype(0), dtype(dtype_), nbargs(1), f1(f), expr(""),
-        derivative1(der), derivative2(""), gis(0) {}
+      : ftype_(0), dtype_(dtype_), nbargs_(1), f1_(f), expr_(""),
+        derivative1_(der), derivative2_("") {}
     ga_predef_function(pscalar_func_twoargs f, size_type dtype_ = 0,
                        const std::string &der1 = "",
                        const std::string &der2 = "")
-      : ftype(0), dtype(dtype_), nbargs(2), f2(f),
-        expr(""), derivative1(der1), derivative2(der2), gis(0) {}
+      : ftype_(0), dtype_(dtype_), nbargs_(2), f2_(f),
+        expr_(""), derivative1_(der1), derivative2_(der2), gis(nullptr) {}
     ga_predef_function(const std::string &expr_)
-      : ftype(1), dtype(3), nbargs(1), expr(expr_),
-        derivative1(""), derivative2(""), t(1), u(1), gis(0) {}
-
-    ~ga_predef_function() { if (gis) delete gis; }
+      : ftype_(1), dtype_(3), nbargs_(1), expr_(expr_),
+        derivative1_(""), derivative2_(""), t(1, 0.), u(1, 0.), gis(nullptr) {}
   };
 
 
@@ -2479,18 +2494,23 @@
                 "Already defined function " << name);
     PREDEF_FUNCTIONS[name] = ga_predef_function(expr);
     ga_predef_function &F = PREDEF_FUNCTIONS[name];
-    F.gis = new ga_instruction_set;
-    F.workspace.add_fixed_size_variable("t", gmm::sub_interval(0,1), F.t);
-    if (nbargs == 2)
-      F.workspace.add_fixed_size_variable("u", gmm::sub_interval(0,1), F.u);
-    F.workspace.add_function_expression(expr);
-    ga_compile_function(F.workspace, *(F.gis), true);
-    F.nbargs = nbargs;
+    GMM_ASSERT1(!me_is_multithreaded_now(),
+                "functions should not be defined in multi-threaded code");
+    F.gis = std::make_unique<omp_distribute<ga_instruction_set>>();
+    for (size_type thread = 0; thread < num_threads(); ++thread)
+    {
+      F.workspace(thread).add_fixed_size_variable("t", gmm::sub_interval(0,1), 
F.t);
+      if (nbargs == 2)
+        F.workspace(thread).add_fixed_size_variable("u", 
gmm::sub_interval(0,1), F.u);
+      F.workspace(thread).add_function_expression(expr);
+      ga_compile_function(F.workspace(thread), (*F.gis)(thread), true);
+    }
+    F.nbargs_ = nbargs;
     if (nbargs == 1) {
-      if (der1.size()) { F.derivative1 = der1; F.dtype = 2; }
+      if (der1.size()) { F.derivative1_ = der1; F.dtype_ = 2; }
     } else {
       if (der1.size() && der2.size()) {
-        F.derivative1 = der1;  F.derivative2 = der2; F.dtype = 2;
+        F.derivative1_ = der1;  F.derivative2_ = der2; F.dtype_ = 2;
       }
     }
   }
@@ -2499,17 +2519,17 @@
                           const std::string &der) {
     PREDEF_FUNCTIONS[name] = ga_predef_function(f, 1, der);
     ga_predef_function &F = PREDEF_FUNCTIONS[name];
-    if (der.size() == 0) F.dtype = 0;
-    else if (!(ga_function_exists(der))) F.dtype = 2;
+    if (der.size() == 0) F.dtype_ = 0;
+    else if (!(ga_function_exists(der))) F.dtype_ = 2;
   }
 
   void ga_define_function(const std::string name, pscalar_func_twoargs f,
                           const std::string &der1, const std::string &der2) {
     PREDEF_FUNCTIONS[name] = ga_predef_function(f, 1, der1, der2);
     ga_predef_function &F = PREDEF_FUNCTIONS[name];
-    if (der1.size() == 0 || der2.size() == 0) F.dtype = 0;
+    if (der1.size() == 0 || der2.size() == 0) F.dtype_ = 0;
     else if (!(ga_function_exists(der1)) || !(ga_function_exists(der2)))
-      F.dtype = 2;
+      F.dtype_ = 2;
   }
 
   void ga_undefine_function(const std::string name) {
@@ -6836,13 +6856,13 @@
           pnode->name = name;
           pnode->test_function_type = 0;
           if (pnode->der1) {
-            if (pnode->der1 > it->second.nbargs
-                || pnode->der2 > it->second.nbargs)
+            if (pnode->der1 > it->second.nbargs()
+                || pnode->der2 > it->second.nbargs())
               ga_throw_error(expr, pnode->pos, "Invalid derivative.");
             const ga_predef_function &F = it->second;
-            if (F.ftype == 0 && !(pnode->der2)) {
+            if (F.ftype() == 0 && !(pnode->der2)) {
               pnode->name = ((pnode->der1 == 1) ?
-                             F.derivative1 : F.derivative2);
+                             F.derivative1() : F.derivative2());
               pnode->der1 = pnode->der2 = 0;
             }
           }
@@ -7102,7 +7122,7 @@
         std::string name = child0->name;
         ga_predef_function_tab::iterator it = PREDEF_FUNCTIONS.find(name);
         const ga_predef_function &F = it->second;
-        size_type nbargs = F.nbargs;
+        size_type nbargs = F.nbargs();
         if (nbargs+1 != pnode->children.size()) {
             ga_throw_error(expr, pnode->pos, "Bad number of arguments for "
                 "predefined function " << name << ". Found "
@@ -8408,22 +8428,22 @@
         ga_predef_function_tab::iterator it = PREDEF_FUNCTIONS.find(name);
         const ga_predef_function &F = it->second;
 
-        if (F.nbargs == 1) {
-          switch (F.dtype) {
+        if (F.nbargs() == 1) {
+          switch (F.dtype()) {
           case 0:
             GMM_ASSERT1(false, "Cannot derive function " << child0->name
                         << ". No derivative provided or not derivable 
function.");
           case 1:
-            child0->name = F.derivative1;
+            child0->name = F.derivative1();
             break;
           case 2: case 3:
             {
               child0->name = "DER_PDFUNC_" + child0->name;
               if (!(ga_function_exists(child0->name))) {
-                if (F.dtype == 2)
-                  ga_define_function(child0->name, 1, F.derivative1);
+                if (F.dtype() == 2)
+                  ga_define_function(child0->name, 1, F.derivative1());
                 else {
-                  std::string expr = ga_derivative_scalar_function(F.expr,"t");
+                  std::string expr = 
ga_derivative_scalar_function(F.expr(),"t");
                   ga_define_function(child0->name, 1, expr);
                 }
               }
@@ -8470,22 +8490,22 @@
             tree.duplicate_with_addition(pnode);
 
           if (child1->marked) {
-            switch (F.dtype) {
+            switch (F.dtype()) {
             case 0:
               GMM_ASSERT1(false, "Cannot derive function " << child0->name
                           << ". No derivative provided");
             case 1:
-              child0->name = F.derivative1;
+              child0->name = F.derivative1();
               break;
             case 2:
               child0->name = "DER_PDFUNC1_" + child0->name;
               if (!(ga_function_exists(child0->name)))
-                ga_define_function(child0->name, 2, F.derivative1);
+                ga_define_function(child0->name, 2, F.derivative1());
               break;
             case 3:
               child0->name = "DER_PDFUNC1_" + child0->name;
               if (!(ga_function_exists(child0->name))) {
-                std::string expr = ga_derivative_scalar_function(F.expr, "t");
+                std::string expr = ga_derivative_scalar_function(F.expr(), 
"t");
                 ga_define_function(child0->name, 2, expr);
               }
               break;
@@ -8507,22 +8527,22 @@
             child0 = pnode->children[0]; child1 = pnode->children[1];
             child2 = pnode->children[2];
 
-            switch (F.dtype) {
+            switch (F.dtype()) {
             case 0:
               GMM_ASSERT1(false, "Cannot derive function " << child0->name
                           << ". No derivative provided");
             case 1:
-              child0->name = F.derivative2;
+              child0->name = F.derivative2();
               break;
             case 2:
               child0->name = "DER_PDFUNC2_" + child0->name;
               if (!(ga_function_exists(child0->name)))
-                ga_define_function(child0->name, 2, F.derivative2);
+                ga_define_function(child0->name, 2, F.derivative2());
               break;
             case 3:
               child0->name = "DER_PDFUNC2_" + child0->name;
               if (!(ga_function_exists(child0->name))) {
-                std::string expr = ga_derivative_scalar_function(F.expr, "u");
+                std::string expr = ga_derivative_scalar_function(F.expr(), 
"u");
                 ga_define_function(child0->name, 2, expr);
               }
               break;
@@ -9918,51 +9938,51 @@
         std::string name = child0->name;
         ga_predef_function_tab::iterator it = PREDEF_FUNCTIONS.find(name);
         const ga_predef_function &F = it->second;
-        size_type nbargs = F.nbargs;
+        size_type nbargs = F.nbargs();
         pga_tree_node child2 = (nbargs == 2) ? pnode->children[2] : child1;
 
         if (nbargs == 1) {
           if (child1->t.size() == 1) {
-            if (F.ftype == 0)
+            if (F.ftype() == 0)
               pgai = new ga_instruction_eval_func_1arg_1res
-                (pnode->t[0], child1->t[0], F.f1);
+                (pnode->t[0], child1->t[0], F.f1());
             else
               pgai = new ga_instruction_eval_func_1arg_1res_expr
                 (pnode->t[0], child1->t[0], F);
           } else {
-            if (F.ftype == 0)
+            if (F.ftype() == 0)
               pgai = new ga_instruction_eval_func_1arg
-                (pnode->t, child1->t, F.f1);
+                (pnode->t, child1->t, F.f1());
             else
               pgai = new ga_instruction_eval_func_1arg_expr
                 (pnode->t, child1->t, F);
           }
         } else {
           if (child1->t.size() == 1 && child2->t.size() == 1) {
-            if (F.ftype == 0)
+            if (F.ftype() == 0)
               pgai = new ga_instruction_eval_func_2arg_1res
-                (pnode->t[0], child1->t[0], child2->t[0], F.f2);
+                (pnode->t[0], child1->t[0], child2->t[0], F.f2());
             else
               pgai = new ga_instruction_eval_func_2arg_1res_expr
                 (pnode->t[0], child1->t[0], child2->t[0], F);
           } else if (child1->t.size() == 1) {
-            if (F.ftype == 0)
+            if (F.ftype() == 0)
               pgai = new ga_instruction_eval_func_2arg_first_scalar
-                (pnode->t, child1->t, child2->t, F.f2);
+                (pnode->t, child1->t, child2->t, F.f2());
             else
               pgai = new ga_instruction_eval_func_2arg_first_scalar_expr
                 (pnode->t, child1->t, child2->t, F);
           } else if (child2->t.size() == 1) {
-            if (F.ftype == 0)
+            if (F.ftype() == 0)
               pgai = new ga_instruction_eval_func_2arg_second_scalar
-                (pnode->t, child1->t, child2->t, F.f2);
+                (pnode->t, child1->t, child2->t, F.f2());
             else
               pgai = new ga_instruction_eval_func_2arg_second_scalar_expr
                 (pnode->t, child1->t, child2->t, F);
           } else {
-            if (F.ftype == 0)
+            if (F.ftype() == 0)
               pgai = new ga_instruction_eval_func_2arg
-                (pnode->t, child1->t, child2->t, F.f2);
+                (pnode->t, child1->t, child2->t, F.f2());
             else
               pgai = new ga_instruction_eval_func_2arg_expr
                 (pnode->t, child1->t, child2->t, F);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]