本节介绍如何使用 er_print 命令行和线程分析器 GUI 显示检测到的每个数据争用的以下信息:
数据争用的唯一 ID。
与数据争用相关联的虚拟地址 Vaddr
。如果不止一个虚拟地址,则会在括号中显示标签 "Multiple Addresses"(多个地址)。
两个不同线程对虚拟地址 Vaddr
的内存访问。将会显示访问的类型(读取或写入),以及源代码中发生访问的函数、偏移量和行号。
与数据争用相关联的调用栈跟踪总数。每个跟踪都引用发生两个数据争用访问时的一对线程调用栈。如果使用的是 GUI,则选择单个调用栈跟踪时会在 "Race Details"(争用详细信息)标签中显示这两个调用栈。如果使用的是 er_print 实用程序,rdetail 命令将会显示这两个调用栈。
要检查 prime_omp.c 中的数据争用,可以使用在2.2.2 创建数据争用检测实验中创建的实验之一。
要使用 er_print 显示 prime_omp_instr.er 实验中的数据争用信息,请键入以下命令。
% er_print prime_omp_inst.er |
在 (er_print) 提示符下,键入 races 可看到类似如下的输出:
(er_print)races Total Races: 2 Experiment: prime_omp_inst.er Race #1, Vaddr: 0x21ca8 Access 1: Write, is_prime, line 26 in "prime_omp.c" Access 2: Read, is_prime, line 23 in "prime_omp.c" Total Callstack Traces: 1 Race #2, Vaddr: (Multiple Addresses) Access 1: Write, main, line 50 in "prime_omp.c" Access 2: Write, main, line 50 in "prime_omp.c" Total Callstack Traces: 2 (er_print) |
该程序的此次特定运行期间发生了两次数据争用。
要在线程分析器中打开 prime_omp_inst.er 实验,请键入以下命令:
% tha prime_omp_inst.er |
以下屏幕抓图显示了在 prime_omp.c 中检测到的争用,如线程分析器所显示。
prime_omp.c 中显示了两个数据争用:
Race #1(争用 1)显示了第 26 行函数 is_prime 中的一次写入与第 23 行同一函数中的一次读取之间的争用。如果查看源代码,可以看到在这些行上,正在对 pflag[ ] 数组进行访问。在线程分析器中,通过单击 "Dual Source"(双源)标签可以很方便地查看位于两个行号位置的源代码,其中还有一些度量显示受影响的代码行上的争用访问次数。
Race #2(争用 2)显示了对 main 函数第 50 行的两次写入之间的争用。单击 "Dual Source"(双源)标签可看到对第 50 行 primes [ ] 数组的值进行了多次访问尝试。
Race #2(争用 2)表示数组 primes[ ] 的不同元素中所发生的一组数据争用。通过 Vaddr
显示 Multiple Addresses(多个地址)可以看出这一点。
使用线程分析器中的 "Dual Source"(双源)标签,可以同时看到与数据争用相关联的两个源代码位置。例如,在 "Races"(争用)标签中选择 prime_pthr.c 的 Race #2(争用 2),然后单击 "Dual Source"(双源)标签。将会看到类似如下的内容。
可能需要在每个源代码面板的标题上拖动鼠标才能看到 "Dual Source"(双源)标签左边界的 "Race Accesses"(竞争访问)度量。
要检查 prime_pthr.c 中的数据争用,可以使用在2.2.2 创建数据争用检测实验中创建的实验之一。
要使用 er_print 显示 prime_pthr_instr.er 实验中的数据争用信息,请键入以下命令:
% er_print prime_pthr_inst.er |
在 (er_print) 提示符下,键入 races 可看到类似如下的输出:
(er_print) races Total Races: 4 Experiment: prime_pthr_inst.er Race #1, Vaddr: (Multiple Addresses) Access 1: Write, is_prime + 0x00000270, line 27 in "prime_pthr.c" Access 2: Write, is_prime + 0x00000270, line 27 in "prime_pthr.c" Total Callstack Traces: 2 Race #2, Vaddr: 0xffbfe714 Access 1: Write, main + 0x0000025C, line 60 in "prime_pthr.c" Access 2: Read, work + 0x00000070, line 40 in "prime_pthr.c" Total Callstack Traces: 1 Race #3, Vaddr: (Multiple Addresses) Access 1: Write, work + 0x00000150, line 44 in "prime_pthr.c" Access 2: Write, work + 0x00000150, line 44 in "prime_pthr.c" Total Callstack Traces: 2 Race #4, Vaddr: 0x21a90 Access 1: Write, work + 0x00000198, line 45 in "prime_pthr.c" Access 2: Write, work + 0x00000198, line 45 in "prime_pthr.c" Total Callstack Traces: 2 (er_print) |
该程序的此次特定运行期间发生了四次数据争用。
要在线程分析器中打开 prime_pthr_inst.er 实验,请键入以下命令:
% tha prime_pthr_inst.er |
以下屏幕抓图显示了在 prime_pthr.c 中检测到的争用,如线程分析器所显示。请注意,这些争用与 er_print 所显示的争用相同。
prime_pthr.c 中显示了四个数据争用:
Race #1(争用 1)是第 27 行函数 is_prime 中对 pflag[ ] 数组的一次写入与同一行中对 pflag[ ] 的另一次写入之间的数据争用。
Race #2(争用 2)是第 60 行中对 main() 中内存位置 i 的一次写入与第 40 行中对同一内存位置(在 work() 中为 *arg)的一次读取之间的数据争用。
Race #3(争用 3)是第 44 行中对 primes[total]
的一次写入与同一行中对 primes[total]
的另一次写入之间的数据争用。
Race #4(争用 4)是第 45 行中对 total 的一次写入与同一行中对 total 的另一次写入之间的数据争用。
如果选择 Race #2(争用 2),然后单击 "Dual Source"(双源)标签,则会看到两个源代码位置,类似于以下屏幕抓图。
Race #2(争用 2)的第一次访问位于第 60 行,显示在顶部面板中。第二次访问位于第 40 行,显示在底部面板中。源代码的左侧会突出显示 "Race Accesses"(争用访问)度量。此度量显示了该行上报告的数据争用访问总次数。
线程分析器的 "Races"(争用)标签中列出的每个数据争用还有一个或多个相关联的调用栈跟踪。这些调用栈显示了代码中导致数据争用的执行路径。单击调用栈跟踪时,右侧面板中的 "Race Details"(争用详细信息)标签会显示导致数据争用的函数调用。