2013-01-19 55 views
3

我有以下程序:OpenMP并行与浮点范围

int main(){ 
    double sum=0; 
    #pragma omp parallel for reduction(+:sum) 
    for(double x=0;x<10;x+=0.1) 
    sum+=x*x; 
} 

当我编译它,我得到的错误invalid type for iteration variable ‘x’

我认为这意味着我只能将parallel for构造应用于基于整数的循环。但是我的循环的内部真的取决于它是浮点。

有没有办法说服OpenMP来做到这一点?有推荐的替代方法吗?

+2

不,由于与给出的答案相同的原因[这里](http://stackoverflow.com/a/13403626/463827);即使它在某些情况下可能会起作用,但编译器并不是非常难以以分解循环的方式推断浮点数。 (甚至这个循环的纯序列优化/矢量化也会因为相同的原因而受到影响)。做一个等价的整数循环并计算你的浮点数; 'for(int i = 0; i <100; i ++){double x = 0.1 * i; sum + = x * x; }' –

+0

@JonathanDursi,如果你把它写成答案,我会接受它。 – Richard

+0

好的,谢谢,我已经在下面做了。 –

回答

6

从评论:

不,OpenMP的不会为你同样的理由这样做如在this answer中给出的关于整数算术的OpenMP循环的问题;编译器很难推断浮点数 - 尤其是编译器在进入循环之前需要知道循环的tripcount,而循环中的浮点运算使得这一般非常困难,即使有一些简单的情况那就没问题了(比如循环0.5到10.0)。因为相同的原因,即使是这种形式的循环的纯序列优化/矢量化也会受到影响。最好的办法是做一个等价的整数循环并根据整数索引计算你的float值;

for (int i=0; i<100; i++) { 
    double x=0.1*i; 
    sum += x*x; 
} 
0

更一般地说,你需要去阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic。 您要添加0.1和期待准确的结果,这一事实表明,你已经没有读过:-)

+0

我已阅读它。我希望没有任何关于我的问题,这意味着我期待确切的结果。我不是。当然,在问题中显示的代码只是一个MWE代码,对于更复杂的代码而言,不需要确切的结果。 – Richard

+1

@Richard,实际上有一些关于你的问题,这意味着你(间接地通过你告诉编译器)期待一种确切的结果。 OpenMP并行循环仅适用于如果可以准确计算循环跳闸次数。 “0.1”是一个无限长度的二进制小数,因此在给定不同的FPU条件下,行程计数可能会得到不同的计算结果。 –

+0

够公平的,@HristoIliev。最终,我可能会最终对当前版本的答案进行投票,因为我不觉得它真的试图回答这个问题。但是,它可以作为评论。我提到这个以防万一你有想法来回答这个问题。 – Richard

0

OpenMP的标准定义的 “for” 循环只为整数,指针和迭代器类型,而不是为浮点类型:

http://www.openmp.org/wp-content/uploads/openmp-4.5.pdf#page=62

2.7.1循环结构

#pragma omp for [clause[ [,] clause] ... ] new-line 
    for-loops 

具体而言,所有相关的for-loops必须具有规范的循环形式 (请参见第2节。 6第53页)。

2.6规范的环形状

环路具有典型循环形式,如果它符合以下几点:

for (init-expr; test-expr; incr-expr) structured-block 

init-expr下列之一:

var = lb 
integer-type var = lb 
random-access-iterator-type var = lb 
pointer-type var = lb 

...

incr-expr以下之一:

++var 
var++ 
-- var 
var -- 
var += incr 
var -= incr 
var = var + incr 
var = incr + var 
var = var - incr 

var下列之一:

  • 有符号或无符号的整数类型的变量。
  • 对于C++,一个随机访问迭代器类型的变量。
  • 对于C,一个指针类型的变量。

规范形式允许所有相关的循环迭代次数,以执行最外层循环

因此,对于非经典类型的编译器无法计算迭代次数之前计算。