检测 OpenMP 竞争
本教程演示如何使用 Coderect 检测使用 OpenMP 编写的单个文件多线程 C 程序中的种族。
先决条件
本教程假定您已经成功地安装了代码处理软件后,快速启动。
我们的示例代码依赖于OpenMP来实现并行性。您将需要一个支持 OpenMP 的编译器。我们将使用gcc,但clang和其他现代替代品也有 OpenMP 支持。
在 pi 中检测比赛.c
我们将从检测一个小的文件程序中的种族开始。该程序旨在计算 pi=3.1415926. …我们在 Coderrect 安装下的示例目录中提供此示例程序,或者您可以将下面的代码复制到您的系统。pi.c
//pi.c
#include <omp.h>
#include <stdio.h>
#define N 1000000000
int main () {
double delta = 1.0/(double) N;
int MAX_THREADS = omp_get_max_threads();
// Compute parallel compute times for 1-MAX_THREADS
for (int j=1; j<= MAX_THREADS; j++) {
printf(" running on %d threads: ", j);
omp_set_num_threads(j);
double sum = 0.0;
double start = omp_get_wtime();
#pragma omp parallel for //reduction(+:sum)
for (int i=0; i < N; i++) {
double x = (i+0.5)*delta;
sum += 4.0 / (1.0+x*x);
}
// Out of the parallel region, finalize computation
double pi = delta * sum;
double time_lapse = omp_get_wtime() - start;
printf("PI = %.12g computed in %.4g seconds\n", pi, time_lapse);
}
}
检查可编译并运行以下命令pi.c
gcc -fopenmp pi.c -o pi
./pi
您应该会看到如下所示的输出:
running on 1 threads: PI = 3.141592653589971 computed in 12.84 seconds
running on 2 threads: PI = 3.141593993623682 computed in 6.928 seconds
running on 3 threads: PI = 3.141594228301372 computed in 7.741 seconds
running on 4 threads: PI = 3.141595112697573 computed in 8.376 seconds
从结果中可以看到,在不同数量的线程上运行生成不同的 PI 值,指示并发错误的存在。
运行编码
运行该工具的最简单方法是将生成命令传递到 :coderrect
coderrect -t gcc -fopenmp pi.c
请记住,生成 pi 的命令.c。gcc -fopenmp pi.c
-t 开关用于在终端中生成快速摘要报告。
这样调用可确保在命令行上传递所有必需的编译标志。对于使用生成系统(如make)的项目,可以使用用于生成项目的相同生成命令调用工具。例如:签出基于Makefile 的项目中检测比赛。coderrectcoderrect
解释结果
该工具直接在终端中报告最有趣的比赛的快速摘要,以便快速查看。该工具还生成更全面的报告,可以在浏览器中查看。coderrect
终端报告
pi 的终端.c应如下所示:
==== Found a race between:
line 22, column 13 in test.c AND line 22, column 17 in test.c
Shared variable:
at line 16 of test.c
16| double sum = 0.0;
Thread 1:
20| for (int i=0; i < N; i++) {
21| double x = (i+0.5)*delta;
>22| sum += 4.0 / (1.0+x*x);
23| }
24|
>>>Stacktrace:
Thread 2:
20| for (int i=0; i < N; i++) {
21| double x = (i+0.5)*delta;
>22| sum += 4.0 / (1.0+x*x);
23| }
24|
>>>Stacktrace:
1 OpenMP races
每个报告的比赛从找到比赛的总结开始。
==== Found a race between:
line 22, column 13 in test.c AND line 22, column 17 in test.c
接下来,报表显示发生比赛的变量名称和位置。
Shared variable:
at line 16 of test.c
16| double sum = 0.0;
这表明比赛发生在第 16 行声明的变量上。sum
在代码中查找比赛位置可能有点乏味,因此报表还显示该位置的文件预览。
Thread 1:
20| for (int i=0; i < N; i++) {
21| double x = (i+0.5)*delta;
22| sum += 4.0 / (1.0+x*x);
23| }
代码片段显示,此赛车访问是作为 OpenMP 并行 for 循环的一部分写入的。sum
仔细看看源代码,我们可以看到根本原因是评论出"减少"。
#pragma omp parallel for //reduction(+:sum)
取消注释将删除数据竞赛,并允许程序正确计算 pi。reduction(+:sum)sum
HTML 报告
终端是伟大的,可以快速了解什么比赛报告,但完整的报告可以在浏览器中查看。
我们还可以将比赛报告保存到通过命令选项指定的目录。-o
coderrect -o report gcc -fopenmp pi.c
这创建了一个名为目录和该目录中命名的文件。若要查看完整报告,请打开浏览器中的文件。reportindex.htmlindex.html