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)
{
try {
expr = new ExprEval::Expression;
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);
size_t nalloc = 1;
#ifdef USE_OPENMP
omp_init_lock(&lock);
nalloc = omp_get_max_threads();
#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) {
ExprException(e,"parsing",function);
@@ -108,31 +116,29 @@ EvalFunc::EvalFunc (const char* function, const char* x)
EvalFunc::~EvalFunc ()
{
delete expr;
delete f;
delete v;
#ifdef USE_OPENMP
omp_destroy_lock(&lock);
#endif
for (auto& it : expr)
delete it;
for (auto& it : f)
delete it;
for (auto& it : v)
delete it;
}
Real EvalFunc::evaluate (const Real& x) const
{
size_t i = 0;
#ifdef USE_OPENMP
omp_set_lock(const_cast<omp_lock_t*>(&lock));
i = omp_get_thread_num();
#endif
Real result = Real(0);
try {
*arg = x;
result = expr->Evaluate();
*arg[i] = x;
result = expr[i]->Evaluate();
}
catch (ExprEval::Exception e) {
ExprException(e,"evaluating expression");
}
#ifdef USE_OPENMP
omp_unset_lock(const_cast<omp_lock_t*>(&lock));
#endif
return result;
}
@@ -141,25 +147,33 @@ Real EvalFunc::evaluate (const Real& x) const
EvalFunction::EvalFunction (const char* function)
{
try {
expr = new ExprEval::Expression;
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");
size_t nalloc = 1;
#ifdef USE_OPENMP
omp_init_lock(&lock);
nalloc = omp_get_max_threads();
#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) {
ExprException(e,"parsing",function);
@@ -174,35 +188,33 @@ EvalFunction::EvalFunction (const char* function)
EvalFunction::~EvalFunction ()
{
delete expr;
delete f;
delete v;
#ifdef USE_OPENMP
omp_destroy_lock(&lock);
#endif
for (auto& it : expr)
delete it;
for (auto& it : f)
delete it;
for (auto& it : v)
delete it;
}
Real EvalFunction::evaluate (const Vec3& X) const
{
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);
try {
*x = X.x;
*y = X.y;
*z = X.z;
*t = Xt ? Xt->t : Real(0);
result = expr->Evaluate();
size_t i = 0;
#ifdef USE_OPENMP
i = omp_get_thread_num();
#endif
*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) {
ExprException(e,"evaluating expression");
}
#ifdef USE_OPENMP
omp_unset_lock(const_cast<omp_lock_t*>(&lock));
#endif
return result;
}

View File

@@ -17,6 +17,7 @@
#include "Function.h"
#include <string>
#include <vector>
#include <array>
#ifdef USE_OPENMP
#include <omp.h>
#endif
@@ -34,11 +35,11 @@ namespace ExprEval {
class EvalFunc : public ScalarFunc
{
ExprEval::Expression* expr; //!< Pointer to the root of the expression tree
ExprEval::FunctionList* f; //!< Pointer to list of function in the expression
ExprEval::ValueList* v; //!< Pointer to list of variables and constants
std::vector<ExprEval::Expression*> expr; //!< Roots of the expression tree
std::vector<ExprEval::FunctionList*> f; //!< Lists of functions
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:
//! \brief The constructor parses the expression string.
@@ -49,11 +50,6 @@ public:
protected:
//! \brief Evaluates the function expression.
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
{
ExprEval::Expression* expr; //!< Pointer to the root of the expression tree
ExprEval::FunctionList* f; //!< Pointer to list of function in the expression
ExprEval::ValueList* v; //!< Pointer to list of variables and constants
std::vector<ExprEval::Expression*> expr; //!< Roots of the expression tree
std::vector<ExprEval::FunctionList*> f; //!< Lists of functions
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
public:
@@ -85,11 +78,6 @@ public:
protected:
//! \brief Evaluates the function expression.
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:
//! \brief The constructor parses the expression string for each component.
EvalMultiFunction<ParentFunc,Ret>(const std::string& functions,
const std::string& variables="")
const std::string& variables = "")
{
size_t pos = functions.find("|"), pos2 = 0;
for (int i = 0; pos2 < functions.size(); i++)
{
std::string func(variables);
if (!func.empty() && func[func.size()-1] != ';')
func += ';';
if (pos == std::string::npos)
func += functions.substr(pos2);
else