我是线程的新手,并且希望能够帮助解决我遇到过的问题。我也是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,代码运行正常。
我读过静态变量可能是罪魁祸首,但不明白为什么。可能问题是库中有一些静态变量我调用的函数之一使用了什么?为什么这会成为问题?我也读过,也许堆栈上没有足够的空间,但也不知道为什么这会阻止关键部分工作,而单线程方法很好。这可能是问题吗?我将如何解决它?
如果您需要更多信息或说明,请与我们联系。非常感谢你的帮助。