changed: instantiate one expr function per thread

this avoids the need for a lock
This commit is contained in:
Arne Morten Kvarving
2015-12-10 07:06:45 +01:00
committed by Knut Morten Okstad
parent 184b9c31e7
commit 3357188686
2 changed files with 79 additions and 81 deletions

View File

@@ -86,19 +86,27 @@ static void ExprException (const ExprEval::Exception& exc, const char* task,
EvalFunc::EvalFunc (const char* function, const char* x) EvalFunc::EvalFunc (const char* function, const char* x)
{ {
try { try {
expr = new ExprEval::Expression; size_t nalloc = 1;
f = new ExprEval::FunctionList;
v = new ExprEval::ValueList;
f->AddDefaultFunctions();
v->AddDefaultValues();
v->Add(x,0,false);
expr->SetFunctionList(f);
expr->SetValueList(v);
expr->Parse(function);
arg = v->GetAddress(x);
#ifdef USE_OPENMP #ifdef USE_OPENMP
omp_init_lock(&lock); nalloc = omp_get_max_threads();
#endif #endif
expr.resize(nalloc);
f.resize(nalloc);
v.resize(nalloc);
expr.resize(nalloc);
arg.resize(nalloc);
for (size_t i = 0; i < nalloc; ++i) {
expr[i] = new ExprEval::Expression;
f[i] = new ExprEval::FunctionList;
v[i] = new ExprEval::ValueList;
f[i]->AddDefaultFunctions();
v[i]->AddDefaultValues();
v[i]->Add(x,0,false);
expr[i]->SetFunctionList(f[i]);
expr[i]->SetValueList(v[i]);
expr[i]->Parse(function);
arg[i] = v[i]->GetAddress(x);
}
} }
catch (ExprEval::Exception e) { catch (ExprEval::Exception e) {
ExprException(e,"parsing",function); ExprException(e,"parsing",function);
@@ -108,31 +116,29 @@ EvalFunc::EvalFunc (const char* function, const char* x)
EvalFunc::~EvalFunc () EvalFunc::~EvalFunc ()
{ {
delete expr; for (auto& it : expr)
delete f; delete it;
delete v; for (auto& it : f)
#ifdef USE_OPENMP delete it;
omp_destroy_lock(&lock); for (auto& it : v)
#endif delete it;
} }
Real EvalFunc::evaluate (const Real& x) const Real EvalFunc::evaluate (const Real& x) const
{ {
size_t i = 0;
#ifdef USE_OPENMP #ifdef USE_OPENMP
omp_set_lock(const_cast<omp_lock_t*>(&lock)); i = omp_get_thread_num();
#endif #endif
Real result = Real(0); Real result = Real(0);
try { try {
*arg = x; *arg[i] = x;
result = expr->Evaluate(); result = expr[i]->Evaluate();
} }
catch (ExprEval::Exception e) { catch (ExprEval::Exception e) {
ExprException(e,"evaluating expression"); ExprException(e,"evaluating expression");
} }
#ifdef USE_OPENMP
omp_unset_lock(const_cast<omp_lock_t*>(&lock));
#endif
return result; return result;
} }
@@ -141,25 +147,33 @@ Real EvalFunc::evaluate (const Real& x) const
EvalFunction::EvalFunction (const char* function) EvalFunction::EvalFunction (const char* function)
{ {
try { try {
expr = new ExprEval::Expression; size_t nalloc = 1;
f = new ExprEval::FunctionList;
v = new ExprEval::ValueList;
f->AddDefaultFunctions();
v->AddDefaultValues();
v->Add("x",0,false);
v->Add("y",0,false);
v->Add("z",0,false);
v->Add("t",0,false);
expr->SetFunctionList(f);
expr->SetValueList(v);
expr->Parse(function);
x = v->GetAddress("x");
y = v->GetAddress("y");
z = v->GetAddress("z");
t = v->GetAddress("t");
#ifdef USE_OPENMP #ifdef USE_OPENMP
omp_init_lock(&lock); nalloc = omp_get_max_threads();
#endif #endif
expr.resize(nalloc);
f.resize(nalloc);
v.resize(nalloc);
expr.resize(nalloc);
c.resize(nalloc);
for (size_t i = 0; i < nalloc; ++i) {
expr[i] = new ExprEval::Expression;
f[i] = new ExprEval::FunctionList;
v[i] = new ExprEval::ValueList;
f[i]->AddDefaultFunctions();
v[i]->AddDefaultValues();
v[i]->Add("x",0,false);
v[i]->Add("y",0,false);
v[i]->Add("z",0,false);
v[i]->Add("t",0,false);
expr[i]->SetFunctionList(f[i]);
expr[i]->SetValueList(v[i]);
expr[i]->Parse(function);
c[i][0] = v[i]->GetAddress("x");
c[i][1] = v[i]->GetAddress("y");
c[i][2] = v[i]->GetAddress("z");
c[i][3] = v[i]->GetAddress("t");
}
} }
catch (ExprEval::Exception e) { catch (ExprEval::Exception e) {
ExprException(e,"parsing",function); ExprException(e,"parsing",function);
@@ -174,35 +188,33 @@ EvalFunction::EvalFunction (const char* function)
EvalFunction::~EvalFunction () EvalFunction::~EvalFunction ()
{ {
delete expr; for (auto& it : expr)
delete f; delete it;
delete v; for (auto& it : f)
#ifdef USE_OPENMP delete it;
omp_destroy_lock(&lock); for (auto& it : v)
#endif delete it;
} }
Real EvalFunction::evaluate (const Vec3& X) const Real EvalFunction::evaluate (const Vec3& X) const
{ {
const Vec4* Xt = dynamic_cast<const Vec4*>(&X); const Vec4* Xt = dynamic_cast<const Vec4*>(&X);
#ifdef USE_OPENMP
omp_set_lock(const_cast<omp_lock_t*>(&lock));
#endif
Real result = Real(0); Real result = Real(0);
try { try {
*x = X.x; size_t i = 0;
*y = X.y; #ifdef USE_OPENMP
*z = X.z; i = omp_get_thread_num();
*t = Xt ? Xt->t : Real(0); #endif
result = expr->Evaluate(); *c[i][0] = X.x;
*c[i][1] = X.y;
*c[i][2] = X.z;
*c[i][3] = Xt ? Xt->t : Real(0);
result = expr[i]->Evaluate();
} }
catch (ExprEval::Exception e) { catch (ExprEval::Exception e) {
ExprException(e,"evaluating expression"); ExprException(e,"evaluating expression");
} }
#ifdef USE_OPENMP
omp_unset_lock(const_cast<omp_lock_t*>(&lock));
#endif
return result; return result;
} }

View File

@@ -17,6 +17,7 @@
#include "Function.h" #include "Function.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <array>
#ifdef USE_OPENMP #ifdef USE_OPENMP
#include <omp.h> #include <omp.h>
#endif #endif
@@ -34,11 +35,11 @@ namespace ExprEval {
class EvalFunc : public ScalarFunc class EvalFunc : public ScalarFunc
{ {
ExprEval::Expression* expr; //!< Pointer to the root of the expression tree std::vector<ExprEval::Expression*> expr; //!< Roots of the expression tree
ExprEval::FunctionList* f; //!< Pointer to list of function in the expression std::vector<ExprEval::FunctionList*> f; //!< Lists of functions
ExprEval::ValueList* v; //!< Pointer to list of variables and constants std::vector<ExprEval::ValueList*> v; //!< Lists of variables and constants
Real* arg; //!< Pointer to the function argument std::vector<Real*> arg; //!< Function argument values
public: public:
//! \brief The constructor parses the expression string. //! \brief The constructor parses the expression string.
@@ -49,11 +50,6 @@ public:
protected: protected:
//! \brief Evaluates the function expression. //! \brief Evaluates the function expression.
virtual Real evaluate(const Real& x) const; virtual Real evaluate(const Real& x) const;
private:
#ifdef USE_OPENMP
omp_lock_t lock;
#endif
}; };
@@ -63,14 +59,11 @@ private:
class EvalFunction : public RealFunc class EvalFunction : public RealFunc
{ {
ExprEval::Expression* expr; //!< Pointer to the root of the expression tree std::vector<ExprEval::Expression*> expr; //!< Roots of the expression tree
ExprEval::FunctionList* f; //!< Pointer to list of function in the expression std::vector<ExprEval::FunctionList*> f; //!< Lists of functions
ExprEval::ValueList* v; //!< Pointer to list of variables and constants std::vector<ExprEval::ValueList*> v; //!< Lists of variables and constants
std::vector<std::array<Real*,4>> c; //!< Function argument values
Real* x; //!< Pointer to the X-coordinate of the function argument
Real* y; //!< Pointer to the Y-coordinate of the function argument
Real* z; //!< Pointer to the Z-coordinate of the function argument
Real* t; //!< Pointer to the time coordinate of the function argument
bool IAmConstant; //!< Indicates whether the time coordinate is given or not bool IAmConstant; //!< Indicates whether the time coordinate is given or not
public: public:
@@ -85,11 +78,6 @@ public:
protected: protected:
//! \brief Evaluates the function expression. //! \brief Evaluates the function expression.
virtual Real evaluate(const Vec3& X) const; virtual Real evaluate(const Vec3& X) const;
private:
#ifdef USE_OPENMP
omp_lock_t lock;
#endif
}; };
@@ -106,16 +94,14 @@ class EvalMultiFunction : public ParentFunc
public: public:
//! \brief The constructor parses the expression string for each component. //! \brief The constructor parses the expression string for each component.
EvalMultiFunction<ParentFunc,Ret>(const std::string& functions, EvalMultiFunction<ParentFunc,Ret>(const std::string& functions,
const std::string& variables="") const std::string& variables = "")
{ {
size_t pos = functions.find("|"), pos2 = 0; size_t pos = functions.find("|"), pos2 = 0;
for (int i = 0; pos2 < functions.size(); i++) for (int i = 0; pos2 < functions.size(); i++)
{ {
std::string func(variables); std::string func(variables);
if (!func.empty() && func[func.size()-1] != ';') if (!func.empty() && func[func.size()-1] != ';')
func += ';'; func += ';';
if (pos == std::string::npos) if (pos == std::string::npos)
func += functions.substr(pos2); func += functions.substr(pos2);
else else