C 在OpenMP中使用GDB

C 在OpenMP中使用GDB,c,gcc,gdb,openmp,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 = o

使用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;
}
我使用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.\u omp\u fn.0
是概述的平行区域
struct.omp_data_s
是一种结构,它保存相应并行区域中引用的所有原语(非数组)共享变量的副本。在本例中,唯一这样的变量是
pub
,因此
struct.omp\u data\u s
只有一个成员
pub
。每个共享变量的值在并行区域启动(1)之前复制到此数据结构中,然后在并行区域结束(2)之后从数据结构中复制回来


发生的情况是,较新版本的GCC不会为
struct.omp_data_s
生成调试信息,因此GDB无法解码
main.\u omp_fn.0
函数的参数。这不受生成的调试信息格式的影响,并且我找不到启用它的选项。我猜这只是因为GDB无法解码较新的GCC生成的调试信息,因为它与Intel的调试器(idb)配合得很好,即它在
info locals
中同时显示
pub
priv
,您使用的GDB/GCC版本是什么?我可以用gdb 7.2和gcc 4.4.7在我的机器上打印“pub”,这两个版本只用-g3-fopenmp标志编译。@robertpreor,我使用的是gcc 4.6.3+gdb 7.4(这些是Ubuntu 12.04LTS存储库中的版本)。我还没有尝试在不同的gcc/gdb版本中编译/调试这段代码,让我来检查一下……使用GCC4.7.3+GDB7.5(在Ubuntu 13.04存储库中),我遇到了同样的问题。没问题。我建议您参考一些关于调试的教科书或教程,因为在堆栈上下移动实际上是最基本的事情之一。对于你的程序来说,只有一个级别是由你编写的,但通常你深入到你编写的函数中,同样的机制也让你在不同级别上检查情况。这个答案是误导性的。您正在
main
函数中打印局部变量
pub
的值。这不是并行区域内使用的共享变量的值,因为GCC将共享OpenMP变量实现为传递到概述区域的结构的成员。插入
pub=110
就在
printf
语句之前,以验证这一点。
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;
}