在OpenMP中使用GDB

使用GDB我似乎无法在OpenMP线程中打印共享变量的值。 例如,使用以下程序:

#include  #include  #include  int main(int argc, char *argv[]) { int priv, tid, pub = 100; #pragma omp parallel private(priv, tid) num_threads(2) { tid = omp_get_thread_num(); priv = tid * 10; #pragma omp sections { #pragma omp section { printf("SECTION 0: tid=%d, priv=%d, pub=%d\n", tid, priv, pub); } #pragma omp section { printf("SECTION 1: tid=%d, priv=%d, pub=%d\n", tid, priv, pub); } } } return EXIT_SUCCESS; } 

在GDB中,如果我在第15行(第0部分的printf)中断,并且我尝试打印“pub”的值,我在当前上下文中得到“No symbol”pub。»消息:

 Breakpoint 1, main._omp_fn.0 () at omp_simplesec.c:15 15 printf("SECTION 0: tid=%d, priv=%d, pub=%d\n", tid, priv, pub); (gdb) print pub No symbol "pub" in current context. 

我正在使用GCC进行编译,并尝试了不同的调试标志(-g3 -ggdb3 -gstabs3 -gstabs + 3),但没有成功。 我也尝试用-O0禁用所有优化,但没有成功。 但是,我可以通过使用-gstabs +标志来查看私有变量的值。

提前致谢。

当我运行你的代码时,我得到了类似的结果。 如果查看回溯,它会告诉您,您所在的OpenMP环境中与GCC实现OpenMP的方式有关。

 (gdb) backtrace #0 main._omp_fn.0 () at tmp.c:15 #1 0x000000000040082e in main (argc=1, argv=0x7fffffffe6c8) at tmp.c:7 

您可以通过以下方式获得pub的值:

 (gdb) up (gdb) print pub $1 = 100 

但这只能获得并行区域之前pub的值。 您应该查看Hristo Iliev的答案,以获得更详细和更好的情况描述。

GCC中的OpenMP使用大纲实现。 这意味着每个并行区域的代码都在其自己的函数中提取。 例如:

 int main(int argc, char *argv[]) { int priv, pub = 100; #pragma omp parallel private(priv) num_threads(2) { printf("priv = %d, pub = %d\n", priv, pub); } return EXIT_SUCCESS; } 

变成了:

 strict .omp_data_s { int pub; }; void main._omp_fn.0(struct .omp_data_s* .omp_data_i) { int priv; printf("priv = %d, pub = %d\n", priv, .omp_data_i->pub); } int main(int argc, char *argv[]) { int priv, pub = 100; struct .omp_data_s .omp_data_o; .omp_data_o.pub = pub; // (1) __builtin_GOMP_parallel_start (main._omp_fn.0, &.omp_data_o, 2); main._omp_fn.0 (&.omp_data_o); __builtin_GOMP_parallel_end (); pub = .omp_data_o.pub; // (2) return EXIT_SUCCESS; } 

main._omp_fn.0是概述的并行区域。 struct .omp_data_s是一个结构,它包含相应并行区域中引用的所有原始(非数组)共享变量的副本 。 在此示例中,唯一的此类变量是pub ,因此struct .omp_data_s具有单个成员pub 。 在并行区域开始(1)之前将每个共享变量的值复制到该数据结构中,然后在并行区域结束之后从数据结构复制回来(2)。

会发生的是,较新版本的GCC不会为struct .omp_data_s生成调试信息,因此GDB无法解码main._omp_fn.0函数的参数。 这不受生成的调试信息格式的影响,我找不到启用它的选项。 我想这只是GDB无法解码较新的GCC产生的调试信息,因为它与英特尔的调试器(idb)运行良好,即它在info locals显示pubpriv