使用openMP进行段错误的原因不明

时间:2015-06-02 14:23:39

标签: c multithreading gdb openmp

我是线程的新手,并且希望能够帮助解决我遇到过的问题。我也是gdb的新手。这是我第一次在这里发帖提问,所以我应该做的任何提示或事情我都会非常感激。

我正在修改用cmake构建的库(用C语言编写)。我在CMakeLists.txt中包含了openMP。

我使用的是Ubuntu 14.04.2,我相信openMP 4.0。

为了使库中的函数运行得更快,我想使用openMP来修改for循环。以下是我正在处理的代码片段:

// now that the arrays are set the threads can be called
// each thread will handle one direction, which corresponds to one fiber
//      tenFiberContext* tfx ... for whole seed
//      tenFiberMulti* tfml ... for whole seed
//      unsigned int dirNum ... 2 for 2 tensor
//      int dirIdx ... 0 or 1 for 2 tensor
//      double* seedData ... pointer to seed voxels stored in memory
//      unsigned int seedNum ... total number of seed voxels
//      int seedIdx ... present seed voxel
//      int i ... present fiber

#
pragma omp parallel
for private(iam, np, dirIdx, seedIdx, fibrIdx, seed)
for (i = 0; i <= fibrNum - 1; i++) {
  //#pragma omp critical
  //{
  np = omp_get_num_threads();
  iam = omp_get_thread_num();
  dirIdx = dirS[i];
  seedIdx = seedNumS[i];
  fibrIdx = i;
  printf("THREAD %d OUT OF %d\ndirIdx: %d\tseedIdx: %d\tfibrIdx: %d\n", iam, np, dirIdx, seedIdx, fibrIdx);
  // tfml and tfx need to be shared

  if (tfx - > verbose > 1) {
    fprintf(stderr, "%s: dir %u/%u on seed %u/%u; len %u; # %u\n", me,
      dirIdx, dirNum, seedIdx, seedNum,
      tfml - > fiberArr - > len, fibrIdx);
  } // prints info about seed, dir, etc. if error

  if (tfml - > fiberArr - > len == fibrIdx) {
    airArrayLenIncr(tfml - > fiberArr, 1);
  } // builds airArray in tfml for all fibers as it goes

  ELL_3V_COPY(tfml - > fiber[fibrIdx].seedPos, seedData + 3 * seedIdx);
  tfml - > fiber[fibrIdx].dirIdx = dirIdx;
  tfml - > fiber[fibrIdx].dirNum = dirNum;
  ELL_3V_COPY(seed, seedData + 3 * seedIdx);

  if (tenFiberSingleTrace(tfx, & (tfml - > fiber[fibrIdx]), seed, dirIdx)) {
    biffAddf(TEN, "%s: trouble on seed (%g,%g,%g) %u/%u, dir %u/%u", me,
      seed[0], seed[1], seed[2], seedIdx, seedNum, dirIdx, dirNum);
  }
  if (tfx - > verbose) {
    if (tenFiberStopUnknown == tfml - > fiber[fibrIdx].whyNowhere) {
      fprintf(stderr, "%s: (%g,%g,%g) ->\n"
        "   steps = %u,%u; len = %g,%g;"
        "whyStop = %s,%s\n", me, seed[0], seed[1], seed[2],
        tfml - > fiber[fibrIdx].stepNum[0],
        tfml - > fiber[fibrIdx].stepNum[1],
        tfml - > fiber[fibrIdx].halfLen[0],
        tfml - > fiber[fibrIdx].halfLen[1],
        airEnumStr(tenFiberStop,
          tfml - > fiber[fibrIdx].whyStop[0]),
        airEnumStr(tenFiberStop, tfml - > fiber[fibrIdx].whyStop[1]));
    } else {
      fprintf(stderr, "%s: (%g,%g,%g) -> whyNowhere: %s\n",
        me, seed[0], seed[1], seed[2],
        airEnumStr(tenFiberStop,
          tfml - > fiber[fibrIdx].whyNowhere));
    } //else
  } // if
  //}

} // for

线程确实开始,并且在线路上的段错误之前完成了一些线程:

ELL_3V_COPY(tfml->fiber[fibrIdx].seedPos, seedData + 3*seedIdx); 

我尝试过不同的私有变量组合,包括但不会导致段错误。

以下是在gdb中运行它后的错误摘录:

Program received signal SIGSEGV, Segmentation fault.
  [Switching to Thread 0x7fffd7b37700(LWP 8848)]
0x00000000005a1841 in tenFiberMultiTrace._omp_fn.0() at / home / jasmine / apps / teem / src / ten / fiber.c: 1179
1179 ELL_3V_COPY(tfml - > fiber[fibrIdx].seedPos, seedData + 3 * seedIdx);
(gdb)
Continuing.
THREAD 7 OUT OF 12
dirIdx: 1 seedIdx: 13 fibrIdx: 27
THREAD 9 OUT OF 12
dirIdx: 1 seedIdx: 16 fibrIdx: 33[Thread 0x7fffd7b37700(LWP 8848) exited]
  [Thread 0x7fffd8b39700(LWP 8846) exited]
  [Thread 0x7fffd933a700(LWP 8845) exited]
  [Thread 0x7fffd9b3b700(LWP 8844) exited]
  [Thread 0x7fffda33c700(LWP 8843) exited]
  [Thread 0x7fffdab3d700(LWP 8842) exited]
  [Thread 0x7fffdb33e700(LWP 8841) exited]
  [Thread 0x7fffdbb3f700(LWP 8840) exited]
  [Thread 0x7fffdc340700(LWP 8839) exited]
  [Thread 0x7fffdcb41700(LWP 8838) exited]
  [Thread 0x7ffff7fd77c0(LWP 8834) exited]
Cannot find user - level thread
for LWP 8847: generic error(gdb)
Continuing.
Cannot execute this command without a live selected thread.

首先,int数组dirS和seedNumS是自动的,所以我为它们分配了内存并且仍然发生了段错误。我的理解是共享tfx,tfml,seedData和seedNum,我希望它们是这样的,以便每个线程可以在内存中的同一点访问它们。此外,tfx和tfml是指向库中包含的头文件中声明的结构的指针。代码片段中还有许多引用到库中其他位置的函数。

我在代码片段中对此进行了评论,但我也尝试将循环的所有内容设置为关键,但这不起作用。如果我在一个线程上运行它而不使用openMP,代码运行正常。

我读过静态变量可能是罪魁祸首,但不明白为什么。可能问题是库中有一些静态变量我调用的函数之一使用了什么?为什么这会成为问题?我也读过,也许堆栈上没有足够的空间,但也不知道为什么这会阻止关键部分工作,而单线程方法很好。这可能是问题吗?我将如何解决它?

如果您需要更多信息或说明,请与我们联系。非常感谢你的帮助。

0 个答案:

没有答案