将GDB与OpenMP一起使用

fak*_*ken 5 c gcc gdb openmp

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

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

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;
}
Run Code Online (Sandbox Code Playgroud)

在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.
Run Code Online (Sandbox Code Playgroud)

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

提前致谢.

Hri*_*iev 13

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;
}
Run Code Online (Sandbox Code Playgroud)

变成了:

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;
}
Run Code Online (Sandbox Code Playgroud)

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不能够解码由新的海湾合作委员会的产生的调试信息,因为它工作得很好,与英特尔的调试器(IDB),即它同时显示pub,并privinfo locals.


Dan*_*dau 1

当我运行你的代码时,我得到类似的结果。如果您查看回溯,它会告诉您您处于与 GCC 如何实现 OpenMP 相关的 OpenMP 环境中。

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

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

(gdb) up
(gdb) print pub
$1 = 100
Run Code Online (Sandbox Code Playgroud)

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