为什么这段使用 openmp 计算 Pi 值的代码每次都会给出略微不同的答案(最后几个浮点数)?
Why does this code which calculates Pi value using openmp gives a slightly different answer(the last few floating points) each time?
这是我使用 openmp 的解决方案,我用它来并行化计算 Pi 的代码。每次执行此操作时,Pi 的浮点值都会发生变化。有人可以解释为什么吗?
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#define THREAD_NUM 20
static long num_steps = 100000;
double step;
int main(){
int i;
double x;
double pi;
double sum = 0.0;
double t1 = 0.0;
double t2 = 0.0;
step = 1.0/(double) num_steps;
omp_set_num_threads(THREAD_NUM);
t1 = omp_get_wtime();
#pragma omp parallel
{
double p_sum = 0.0;
#pragma omp for
for(i=0; i<num_steps; i++){
x = (i+0.5)*step;
p_sum = p_sum + 4.0/(1.0+x*x);
}
#pragma omp atomic
sum += p_sum;
}
t2 = omp_get_wtime();
pi = step*sum;
printf("value of pi = %lf\n", pi);
printf("time = %lf ms\n", (t2-t1)*1000);
}
浮点加法既不是关联的也不是交换的!这意味着您获得的确切值取决于 p_sum
/sum
的组件相加的顺序。要准确理解为什么您必须理解浮点加法在实践中是如何工作的。我建议阅读 What Every Computer Scientist should Know About Floating-Point Arithmetic.
正如@Gilles 在问题下的评论中指出的那样,问题出在声明为共享变量的 x 变量上。它应该声明为私有变量。
...
#pragma omp parallel
{
double x;
double p_sum = 0.0;
#pragma omp for
for(i=0; i<num_steps; i++){
...
这是我使用 openmp 的解决方案,我用它来并行化计算 Pi 的代码。每次执行此操作时,Pi 的浮点值都会发生变化。有人可以解释为什么吗?
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#define THREAD_NUM 20
static long num_steps = 100000;
double step;
int main(){
int i;
double x;
double pi;
double sum = 0.0;
double t1 = 0.0;
double t2 = 0.0;
step = 1.0/(double) num_steps;
omp_set_num_threads(THREAD_NUM);
t1 = omp_get_wtime();
#pragma omp parallel
{
double p_sum = 0.0;
#pragma omp for
for(i=0; i<num_steps; i++){
x = (i+0.5)*step;
p_sum = p_sum + 4.0/(1.0+x*x);
}
#pragma omp atomic
sum += p_sum;
}
t2 = omp_get_wtime();
pi = step*sum;
printf("value of pi = %lf\n", pi);
printf("time = %lf ms\n", (t2-t1)*1000);
}
浮点加法既不是关联的也不是交换的!这意味着您获得的确切值取决于 p_sum
/sum
的组件相加的顺序。要准确理解为什么您必须理解浮点加法在实践中是如何工作的。我建议阅读 What Every Computer Scientist should Know About Floating-Point Arithmetic.
正如@Gilles 在问题下的评论中指出的那样,问题出在声明为共享变量的 x 变量上。它应该声明为私有变量。
...
#pragma omp parallel
{
double x;
double p_sum = 0.0;
#pragma omp for
for(i=0; i<num_steps; i++){
...