Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using GDB with OpenMP

Tags:

c

gcc

gdb

openmp

Using GDB I can't seem to print the value of shared variables within OpenMP threads. For example, using the following program:

#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;
}

In GDB, if I break at line 15 (the printf of section 0), and I try to print the value of "pub", I get the «No symbol "pub" in current context.» message:

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.

I am compiling with GCC, and tried different debugging flags (-g3 -ggdb3 -gstabs3 -gstabs+3), without success. I also tried disabling all optimizations with -O0, again with no success. However, I can see the value of private variables by using the -gstabs+ flag.

Thanks in advance.

like image 976
faken Avatar asked Sep 12 '13 15:09

faken


2 Answers

OpenMP in GCC is implemented using outlining. It means that the code for each parallel region is extracted in its own function. For example:

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

gets transformed into:

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 is the outlined parallel region. struct .omp_data_s is a structure that holds copies of all primitive (non-array) shared variables referenced in the corresponding parallel region. In this example the only such variable is pub and therefore struct .omp_data_s has a single member pub. The value of each shared variable is copied into this data structure before the parallel region is started (1) and then copied back from the data structure after the parallel region has ended (2).

What happens is that newer versions of GCC do not generate debug information for the struct .omp_data_s and therefore GDB cannot decode the arguments of the main._omp_fn.0 function. This is not affected by the format of the debug info being generated and I found no option that enables it. I guess it's just GDB not being able to decode the debug info produced by newer GCC's since it works pretty well with Intel's debugger (idb), i.e. it shows both pub and priv in info locals.

like image 183
Hristo Iliev Avatar answered Oct 13 '22 10:10

Hristo Iliev


When I run your code I get similar results. If you look at the backtrace, it tells you that you are inside an OpenMP environment that is related to how GCC implements OpenMP.

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

You can get a value of pub by:

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

but this only gets you the value of pub before the parallel region. You should check the answer by Hristo Iliev for a much more detailed and better description of the situation.

like image 42
Daniel Landau Avatar answered Oct 13 '22 12:10

Daniel Landau