2014-03-27 55 views
11

我需要編寫一個程序,其中字符串表達式的評估相當頻繁。一個表達式的例子如下:在多線程程序中使用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; 

} 

請注意,這是測試代碼。實際上,每個線程都將使用不同的一組值來評估表達式。這段代碼工作正常,但我需要讓它變得更快。

基於其他一些實驗,我發現我不能共享一個具有多個線程的符號表來更快地計算單個表達式。在多個線程中共享符號表導致內存損壞錯誤。

有人可以請提供一些關於如何提高性能的建議。

+2

考慮使用'std :: vector&zrlist'。然後你也可以使用'symbol_table.add_vector(「a」,zrlist);'注意,第二個參數是通過引用(而不是'const')傳遞給'add_variable/add_vector',它的值可以通過'exprtk' 。 –

+1

您的多線程應用程序失敗,因爲exprtk不是線程安全的。因此,不能在沒有競爭和內存損壞的情況下在多個線程上共享一個對象/表。 –

回答

5

您可以嘗試構建exprtk對象一次,併爲每個線程創建它們的副本。如果複製exprtk對象比構建它們快,這應該會更快。

13

假設,你有N線程。比,創建在程序Nexprtk - 相關對象(包括symbol_tableexpressionparser)的(外的功能,和外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..)

您還可以創建一組對象,並通過複製來創建其他對象,如Aloalosuggested

P.S.傾向於使用智能指針,https://stackoverflow.com/a/19042634 不要忘記刪除本地分配的內存。

相關問題