c - OpenMP 输出不正确的答案
问题描述
我输入了这个简单的代码来计算 2 到 5,000,000 之间的素数个数。该算法工作正常,它输出正确的答案,但是当我尝试使用 OpenMP 来加速执行时,它每次都会输出不同的答案。
#include "time.h"
#include "stdio.h"
#include "omp.h"
int main()
{
clock_t start = clock();
int count = 1;
int x;
bool flag;
#pragma omp parallel for schedule(static,1) num_threads(2) shared(count) private(x,flag)
for (x = 3; x <= 5000000; x+=2)
{
flag = false;
if (x == 2 || x == 3)
count++;
else if (x % 2 == 0 || x % 3 == 0)
continue;
else
{
for (int i = 5; i * i <= x; i += 6)
{
if (x % i == 0 || x % (i + 2) == 0)
{
flag = true;
break;
}
}
if (!flag)
count++;
}
}
clock_t end = clock();
printf("The execution took %f ms\n", (double)end - start / CLOCKS_PER_SEC);
printf("%d\n", count);
}
该代码不适用于任何数量的线程、动态或静态调度或不同的块大小。我试过弄乱私有和共享变量,但它仍然不起作用,并且在 for 循环中声明 x 和 flag 也不起作用。我正在使用 Visual Studio 2019,并且启用了 OpenMP 支持。我的代码有什么问题?
解决方案
您的count
变量存在竞争条件,多个线程可以尝试同时更新它。简单的解决方法是使用 OpenMPreduction()
子句为每个线程提供变量的私有副本,并让它们全部正确添加:
#include <time.h>
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
clock_t start = clock();
int count = 1;
#pragma omp parallel for schedule(static,1) num_threads(2) reduction(+:count)
for (int x = 3; x <= 5000000; x+=2)
{
bool flag = false;
if (x == 2 || x == 3)
count++;
else if (x % 2 == 0 || x % 3 == 0)
continue;
else
{
for (int i = 5; i * i <= x; i += 6)
{
if (x % i == 0 || x % (i + 2) == 0)
{
flag = true;
break;
}
}
if (!flag)
count++;
}
}
clock_t end = clock();
printf("The execution took %f ms\n", (double)end - start / CLOCKS_PER_SEC);
printf("%d\n", count);
}
这将输出 348513(通过其他软件验证为正确的数字)。
还要注意清理标题并移动一些变量声明以避免需要private()
子句。
您也可以创建count
一个原子 int,但这比reduction()
在我的测试中使用要慢。
推荐阅读
- android - 禁用 Android TV 上的默认焦点行为
- azure - 逻辑应用:使用另一个帐户发送邮件
- javascript - 将 knex 与 es6 模块一起使用
- git - Git 存储库:文件未反映最新提交
- javascript - 如何在 vue/nuxt 中导入几十个 svg 文件
- java - 为什么我的代码中不断出现 arrayIndexOutOfBound 异常错误
- nginx - Nginx、nuxt.js 静态生成模式和尾部斜杠重定向
- python - 使用 Python/boto3 更新 S3 存储桶中的静态网页
- ruby-on-rails - 使用设计时在模型上自动设置 created_by
- reactjs - 如何在标头中传递授权令牌以响应 Axios.post?