除了调试多线程程序这一常规功能外,dbx 还可以调试 OpenMP 程序。
dbx 可以单步步入并行区域。因为并行区域是外联区域并从 OpenMP 运行时库中进行调用,所以单步执行实际涉及几个层次的运行时库调用(这些调用由为此目的而创建的线程执行)。单步步入并行区域时,到达断点的第一个线程引起程序停止。此线程可能是从属线程而不是启动单步执行的主线程。
例如,请参阅编译器如何转换 OpenMP 代码中的 Fortran 代码,并假定主线程 t@1 位于第 10 行。当您单步执行到第 12 行时,将创建从属线程 t@2、t@3 和 t@4 来执行运行时库调用。线程 t@3 首先到达断点并导致程序停止执行。因此,由线程 t@1 启动的单步执行在线程 t@3 上结束。此行为不同于正常的单步执行(在正常的单步执行后,通常仍处在与此前相同的线程上)。
dbx 可以输出所有共享、专用和线程专用变量。如果尝试输出并行区域之外的线程专用变量,将输出主线程的副本。whatis 命令用于输出并行构造内共享变量和专用变量的数据共享属性。对于线程专用变量,无论这些变量是否在并行构造内,都将输出其数据共享属性。例如:
(dbx) whatis p_a # OpenMP first and last private variable int p_a;
print -s expression 命令用于输出当前 OpenMP 并行区域中每个线程的 expression 表达式的值(如果该表达式包含专用变量或线程专用变量)。例如:
(dbx) print -s p_a thread t@3: p_a = 3 thread t@4: p_a = 3
如果该表达式不包含任何专用变量或线程专用变量,将仅输出一个值。
dbx 可以输出当前并行区域或指定并行区域的描述,其中包括父区域、并行区域 ID、组大小(线程数)以及程序位置(程序计数器地址)。例如:
(dbx) omp_pr parallel region 127283434369843201 team size = 4 source location = test.c:103 parent = 127283430568755201
它还可以输出所有并行区域的描述以及从当前并行区域或指定并行区域到其根目录的路径。例如:
(dbx) omp_pr -ancestors parallel region 127283434369843201 team size = 4 source location = test.c:103 parent = 127283430568755201 parallel region 127283430568755201 team size = 4 source location = test.c:95 parent = <no parent>
它也可以输出整个并行区域树。例如:
(dbx) omp_pr -tree parallel region 127283430568755201 team size = 4 source location = test.c:95 parent = <no parent> parallel region 127283434369843201 team size = 4 source location = test.c:103 parent = 127283430568755201
有关更多信息,请参见omp_pr 命令。
dbx 可以输出当前任务区域或指定任务区域的描述,其中包括任务区域 ID、状态(已产生、正在执行、正在等待)、正在执行的线程、程序位置(程序计数器地址)、未完成子项以及父项。例如:
(dbx) omp_tr task region 65540 type = implicit state = executing executing thread = t@4 source location == test.c:46 unfinished children = 0 parent = <no parent>
它还可以输出所有任务区域的描述以及从当前任务区域或指定任务区域到其根目录的路径。
(dbx) omp_tr -ancestors task region 196611 type = implicit state = executing executing thread = t@3 source location - test.c:103 unfinished children = 0 parent = 131075 task region 131075 type = implicit state = executing executing thread = t@3 unfinished children = 0 parent = <no parent>
它也可以输出整个任务区域树。例如:
(dbx) omp_tr -tree task region 10 type = implicit state = executing executing thread = t@10 source location = test.c:103 unfinished children = 0 parent = <no parent> task region 7 type = implicit state = executing executing thread = t@7 source location = test.c:103 unfinished children = 0 parent = <no parent> task region 6 type implicit state = executing executing thread = t@6 source location = test.c:103 unfinished children = 0 parent = <o parent> task region 196609 type = implicit state = executing executing thread = t@1 source location = test.c:95 unfinished children = 0 parent = <no parent> task region 262145 type = implicit state = executing executing thread = t@1 source location = test.c:103 unfinished children - 0 parent = 196609
有关更多信息,请参见omp_tr 命令。
dbx 可以输出当前循环的描述,其中包括调度类型(静态、动态、指导、自动或运行时)、有序性、界限、步幅或跨距以及迭代数。例如:
(dbx) omp_loop ordered loop: no lower bound: 0 upper bound: 3 step: 1 chunk: 1 schedule type: static source location: test.c:49
有关更多信息,请参见omp_loop 命令。
(dbx) omp_team team members: 0: t@1 state = in implicit barrier, task region = 262145 1: t@6 state = in implicit barrier, task region = 6 2: t@7 state = working, task region = 7 3: t@10 state = in implicit barrier, task region = 10
有关更多信息,请参见omp_team 命令。
调试 OpenMP 代码时,除有关当前或指定线程的常规信息外,thread -info 还将输出 OpenMP 线程 ID、并行区域 ID、任务区域 ID 及 OpenMP 线程状态。有关更多信息,请参见thread 命令。
dbx 命令可以将当前线程或当前组中的所有线程遇到的下一个并行区域的执行序列化。有关更多信息,请参见omp_serialize 命令。
当执行在并行区域中停止时,where 命令会显示包含外联子例程的栈跟踪。
(dbx) where current thread: t@4 =>[1] _$d1E48.main(), line 52 in "test.c" [2] _$p1I46.main(), line 48 in "test.c" --- frames from parent thread --- current thread: t@1 [7] main(argc = 1, argv = 0xffffffff7fffec98), line 46 in "test.c"
栈的顶帧是外联函数帧。尽管代码是外联的,源代码行号仍映射回 15。
当执行在并行区域中停止时,如果相关帧仍处于活动状态,来自从属线程的 where 命令将输出主线程的栈跟踪。来自主线程的 where 命令具有完全的回溯。
也可以首先使用 omp_team 命令列出当前组中的所有线程,然后切换到主线程(OpenMP 线程 ID 为 0 的线程)并从该线程获得栈跟踪,以此来确定执行到达从属线程中断点的方式。
当执行在并行区域中停止时,dump 命令可以输出专用变量的多个副本。在下例中,dump 命令输出变量 i 的两个副本:
[t@1 l@1]: dump i = 1 sum = 0.0 a = ARRAY i = 1000001
因为外联例程作为宿主例程的嵌套函数实现,而专用变量作为外联例程的局部变量实现,所以会输出变量 i 的两个副本。由于 dump 命令输出作用域内的所有变量,因此宿主例程中的 i 和外联例程中的 i 均会显示。
dbx 提供了可以与 stop、when 和 trace 命令结合用于 OpenMP 代码的事件。有关将事件与这些命令结合使用的信息,请参见设置事件规范。
跟踪线程进入屏障事件。
type 可以是以下值:
explicit,表示跟踪显式屏障
implicit,表示跟踪隐式屏障
如果不指定 type,则只跟踪显式屏障。
state 可以是以下值:
enter,表示在有线程进入屏障时报告该事件
exit,表示在有线程退出屏障时报告该事件
all_entered,表示在所有线程都进入屏障时报告该事件
如果不指定 state,缺省值为 all_entered。
如果指定 enter 或 exit,可以设置线程 ID 以指定仅跟踪该线程。
跟踪线程进入任务等待事件。
state 可以是以下值:
enter,表示在线程进入任务等待时报告该事件
exit,表示在所有子任务都已完成时报告该事件
如果不指定 state,缺省值为 exit。
跟踪线程进入有序区域事件。
state 可以是以下值:
begin,表示在有序区域开始时报告该事件
enter,表示在线程进入有序区域时报告该事件
exit,表示在线程退出有序区域时报告该事件
如果不指定 state,则缺省值为 enter。
跟踪线程进入关键区域事件。
跟踪线程进入原子区域事件。
state 可以是以下值:
begin,表示在原子区域开始时报告该事件
exit,表示在线程退出原子区域时报告该事件
如果不指定 state,缺省值为 begin。
跟踪线程执行刷新事件。