5

使用 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;
}

在 GDB 中,如果我在第 15 行中断(第 0 节的 printf),并尝试打印 "pub" 的值,我会得到 «No symbol "pub" in current context。» 信息:

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+ 标志查看私有变量的值。

提前致谢。

4

2 回答 2

16

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) 配合得很好,即它pub同时显示priv.info locals

于 2013-09-13T14:59:18.510 回答
2

当我运行您的代码时,我会得到类似的结果。如果您查看回溯,它会告诉您您处于与 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

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

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

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

于 2013-09-12T17:35:36.903 回答