外部声明全局变量后的Threadprivate指令

时间:2014-08-01 23:06:47

标签: c++ multithreading openmp

我有四个全局变量

extern Vars vars;
extern Params params;
extern Workspace work;
extern Settings settings

我正在尝试使用以下方式将线程设为私有:

#pragma omp threadprivate(vars,params,work,settings)

然后我调用这个函数:

void parallelSolver(void *handle, Params *paramsIn, double* data, int dataNum){
  int i; 
  #pragma omp parallel for
  for (i = 0; i < dataNum; i++) {  // Main control loop.
    Params paramsOW = load_data(*paramsIn, data, i);
    csolve(paramsOW);
  }
}

将每个单独运行的数据加载到paramsOW,然后调用:

void csolve(Params paramsIn){
  set_defaults();  // Set basic algorithm parameters.
  setup_indexing();

  params = paramsIn;

  printValues(params); 

  // Solve our problem at high speed!
  long num_iters = solve();
  // Recommended: check work.converged == 1.

  //  use_solution(vars);
}

调用solve()调用许多使用这些全局变量的函数。我宁愿能够将Vars,Params,Workspace和Settings作为参数传递给solve(),但编写代码的方式,我必须遵循的范例是,它使我们成为这些全局变量。我在尝试编译此代码时遇到的错误是:

$ gcc -fopenmp -shared -Wl,-soname,runSolverParalle -o runSolverParallel.so -fPIC runSolverParallel.c solver.c ldl.c matrix_support.c 
/usr/bin/ld: work: TLS reference in /tmp/cc7BbGwf.o mismatches non-TLS reference in /tmp/ccbUwz29.o
/tmp/ccbUwz29.o: could not read symbols: Bad value
collect2: ld returned 1 exit status

注意我正在将其编译为共享对象,因为我使用cython和python代码发送parallelSolver实例化它的数据。当我消除threadprivate减速时,它编译并正常工作(减去由于所有线程使用相同的全局变量而存在的竞争条件)。

编辑:是全局变量是一种癌症,处理这个代码库非常令人沮丧。我没有编写底层代码,必须使用它来并行运行一个简单的测试用例。因此,完全不值得我重构底层代码库。感谢Massimiliano阅读我所说的内容,而不是跳上全球变量讨厌的火车。

2 个答案:

答案 0 :(得分:4)

发生的事情很可能是插入threadprivate子句不在声明全局变量的标头内部的效果。

实际上,一个翻译单元将变量视为非TLS (线程本地存储),而另一个翻译单元将其视为 TLS 。这最终会产生链接错误。

解决方案是在声明那些全局变量的标题中插入threadprivate指令(当然要使用该标头在任何地方声明它们)。

答案 1 :(得分:-1)

全球变量是一种癌症。消除它们并且你不会有链接错误,而且你的代码可能实际上有点可维护。