Использование exprtk в многопоточной программе

Мне нужно написать программу, в которой строковые выражения вычисляются довольно часто. Пример выражения приведен ниже:

"x0*a0*a0+x1*a1+x2*a2+x3*a3+x4*a4....."

Выражения могут быть длинными, и строка может содержать несколько таких выражений.

Я написал тестовый код, используя библиотеку C ++ exprtk.

vector<std::string> observation_functions;
vector<std::string> string_indices;template<typename T>
float* get_observation(float* sing_j, float* zrlist, int num_functions,int num_variables)
{
//omp_set_nested(1);

float* results = (float*)malloc(sizeof(float)*num_functions);
exprtk::symbol_table<float> symbol_table;

exprtk::expression<T> expression;
exprtk::parser<T> parser;
int i;
for( i = 0; i < num_variables; i++)
{
symbol_table.add_variable("x"+string_indices[i], sing_j[i]);
symbol_table.add_variable("a"+string_indices[i], zrlist[i]);
}

expression.register_symbol_table(symbol_table);
for(i = 0; i < num_functions; i++)
{
parser.compile(observation_functions[i],expression);
results[i] = expression.value();
}
return results;
}int main()
{

for( int i = 0; i < 52; i++)
{

ostringstream s2;
s2<<i;
string_indices.push_back(s2.str());
}string hfun ="x0*a0*a0+x1*a1+x2*a2+x3*a3+x4*a4+x5*a5+x6*a6+x7*a7+x8*a8+x9*a9+x10*a10+x11*a11+x12*a12+x13*a13+x14*a14+x15*a15+x16*a16+x17*a17+x18*a18+x19*a19+x20*a20+x21*a21+x22*a22+x23*a23+x24*a24+x25*a25+x26*a26+x27*a27+x28*a28+x29*a29+x30*a30+x31*a31+x32*a32+x33*a33+x34*a34+x35*a35+x36*a36+x37*a37+x38*a38+x39*a39+x40*a40+x41*a41+x42*a42+x43*a43+x44*a44+x45*a45+x46*a46+x47*a47+x48*a48+x49*a49+x50*a50+x51*a51 ";boost::split(observation_functions, hfun, boost::is_any_of(" "));
float *a=(float*)malloc(52*sizeof(float));
float* c=(float*)malloc(52*sizeof(float));

struct timeval t0,t1;
gettimeofday(&t0, 0);
for(int j=0; j < 210; j++)
#pragma omp parallel for schedule(static,1) num_threads(8)
for(int i=0;i<104;i++)
float* b =get_observation<float>(a,c,1,52);
gettimeofday(&t1, 0);
long elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec;
cout<<"elapsed:"<<elapsed<<endl;

}

Обратите внимание, что это тестовый код. В действительности каждый поток будет оценивать выражение с различным набором значений. Этот код работает нормально, но мне нужно, чтобы он работал быстрее.

Основываясь на некоторых других экспериментах, я обнаружил, что не могу совместно использовать одну таблицу символов с несколькими потоками для более быстрого вычисления одного выражения. Совместное использование таблицы символов среди нескольких потоков привело к ошибкам повреждения памяти.

Может кто-нибудь дать несколько советов о том, как я могу улучшить производительность.

11

Решение

Предположим, у вас есть N потоки. Чем создать N наборы exprtkсвязанные объекты (в том числе symbol_table, expression, parser) в главный программа (вне функция и снаружи for петли).

Вы могли бы использовать vector<> хранить их: например, для expression объекты это будет vector<expression> expressions;

Затем передайте ссылки на эти объекты при вызове вашей функции,

for(int i=0;i<104;i++)
get_observation<float>(expressions[i], more params here..)

Определение функции шаблона:
template <typename T> T* get_observation(expression & exp, more params here..)

Вы также можете создать один набор объектов и создать другой, скопировав, как Aloalo предложенный.

Постскриптум Предпочитаю использовать умные указатели, https://stackoverflow.com/a/19042634
не забудьте удалить память, выделенную где-то локально.

13

Другие решения

Вы можете попробовать создать объекты exprtk только один раз и скопировать их для каждого потока. Это должно быть быстрее, если копирование объектов exprtk происходит быстрее, чем их создание.

5

По вопросам рекламы [email protected]