我试图在 OpenMP 中平行使用一个相当巨大的 < code> for- loop code> 。 大约20%的运行时间顺利, 但剩下的时间它会与各种断层发生碰撞, 例如 ;
*** glibc detected *** ./execute: double free or corruption (!prev): <address> ***
*** glibc detected *** ./execute: free(): invalid next size (fast): <address> ***
[2] <PID> segmentation fault ./execute
我的一般代码结构如下:
<declare and initialize shared variables here>
#pragma omp parallel private(list of private variables which are initialized in for loop) shared(much shorter list of shared variables)
{
#pragma omp for
for (index = 0 ; index < end ; index++) {
// Lots of functionality (science!)
// Calls to other deep functions which manipulate private variables
// Finally generated some calculated_values
shared_array1[index] = calculated_value1;
shared_array2[index] = calculated_value2;
shared_array3[index] = calculated_value3;
时 时 // end for
时 时
// final tidy up
时 时
就目前的情况而言,每个循环迭代完全独立于其他循环迭代,而不是它们从共享矩阵中提取数据(但每个循环迭代中各列列 ) 。 在我称之为其他函数时,它们只是改变私人变量(尽管偶尔读取共享变量 ), 所以我假设它们会是安全的线条,因为它们只是把本地的东西混杂到特定的线条上。 对任何共享变量的唯一写法发生在最后, 我们把各种计算值写入一些共享的阵列, 在那里, 阵列元素由循环索引索引索引索引索引索引索引索引。 这个代码在 C++ 中, 尽管它所呼吁的代码是 C 和 C++ 代码 。
我一直试图找出问题的根源,但目前还没有结果。如果我设置 num_theads(1), 问题会很好, 就象我把 < code> for-loop 的内容合并成单条一样。
#pragma omp for
for(index = 0 ; index < end ; index++) {
#pragma omp critical(whole_loop)
{
// loop body
时 时
时 时
也就是说,在任何一个时间,只有一条线可以穿过循环圈。
另一方面,如果将 for-loop s
内容附加在两个 批判性
指令中,例如:
#pragma omp for
for(index = 0 ; index < end ; index++) {
#pragma omp critical(whole_loop)
{
// first half of loop body
时 时
#pragma omp critical(whole_loop2)
{
// second half of loop body
时 时
时 时
我得到了不可预知的断层。 同样, 如果我在 < code> 关键 < /code > 指令中附上每个函数呼叫, 它仍然无效 。
我认为问题可能与函数调用相关的原因是,当我使用Valgrind (使用 valgrind --tool=drd -- check-stack-var=yes -- read-var-info=yes./execute
)的配置以及SIGSEGing(使用 insane 的负载和存储错误数量,例如:
Conflicting load by thread 2 at <address> size <number>
at <address> : function which is ultimately called from within my for loop
org/docs/ manual/drd-manual.html#drd-manual.data-races" rel=“nofollow”> Valgrind 手册 恰恰是种族条件所期望的。 当然,这种怪异的出现/消失问题似乎与非确定性错误种族条件的种类一致,但是我不明白,如果每次给出明显种族条件的呼声都出现在一个关键部分里,那又如何呢?
可能是错的,但我不认为它包含在内;
所有() 私有变量都在
for-loops
内初始化( 因为它们重线为本地 ) 。我检查过共享变量有相同的内存地址 而私人变量有不同的内存地址
我不确定同步会有所帮助,但鉴于有隐含的
barrier
出入境指令批判
指令,我已尝试过我的代码版本,其中每个功能电话都包含在一个(唯一命名的)关键章节中,我认为我们可以排除这一点。
任何关于最佳操作方法的想法都会非常感激。 坚固> 我一整天都在用头顶着这个。 显然我并不想用“ 哦 - 这里就是问题” 这样的答案, 但是在调试/ 解构方面,如何做最好。
可能是一个问题或可能有所帮助的事情;
有一些 std: : 使用矢量. pushback () 函数添加元素的代码中的导体。 我记得读到过, 调整矢量的大小不安全, 但矢量只是私人变量, 所以不在线条之间共享。 我想这样可以吗?
如果我将整个
for-loop
体中的所有for-loop
都附加在关键
指令中,并慢慢地缩回代码区末(因此,在代码区末端的for-loop
正在不断增长的区域在关键区段之外),它就会运行正常,直到我暴露一个函数调用时,该函数会恢复连接。用 Valgrind 分析此二进制在许多其他函数中显示种族条件, 而不仅仅是我所暴露的函数 。其中一项功能是GSL函数,根据Valgrind的说法,它不会触发任何种族条件。
我是否需要去明确定义调用函数中的私人变量和共享变量? 如果需要的话,这似乎对 OpenMP 有点限制 - 这是否意味着您需要对您调用的任何遗留代码具有 OpenMP 兼容性?
平行使用一个大的
for-loop
是否有效?如果你读了这么远的话,谢谢你们,祝你们一路顺风。