首页 文章

ICC编译器 - 错误:并行循环条件不测试循环控制变量

提问于
浏览
1

我试图在英特尔MIC(Xeon Phi)卡上卸载调用后并行化我的C / OpenMP代码的“for循环” . 我正在使用“#pragma omp parallel for”,当我使用整数变量作为“循环控制变量”时,它编译得很好 . 在我的代码中我使用浮点数组作为“循环控制变量”然后我得到错误“并行循环条件不测试循环控制变量” .

代码没有错误:

#define MAX_DIMENSIONS  10

unsigned long long  i,y=0;

#pragma offload target(mic) in(i,y)
{
    #pragma omp parallel for
    for(i=0;i<10;i++)
        /* code here */  
}

代码有错误:

#define MAX_DIMENSIONS  10

float   x[MAX_DIMENSIONS];
unsigned long long  i,y=0;

#pragma offload target(mic) in(x[MAX_DIMENSIONS],i,y)
{
    #pragma omp parallel for
    for(x[0]=0.000000; x[0]<10.000000; x[0]+=1.000000)
        /* code here */
}

有没有办法在“for循环”中保留浮点数组表示法,以便使用OpenMP成功并行化?

2 回答

  • 4

    您可以像这样手动实现工作共享

    #pragma omp parallel
    {
        float a = 0., b = 10.;
        float step = 1.;
        int N = (b-a)/step;
        int ithread = omp_get_thread_num();
        int nthreads = omp_get_num_threads();
        float t0 = (ithread+0)*N/nthreads + a;
        float t1 = (ithread+1)*N/nthreads + a;
        for(float x=t0; x<t1; x += step) {
          //code
        }
    }
    

    这相当于

    #pragma omp parallel for 
    for(float x=a; x<b; x += step)
    

    如果 omp for 构造支持浮点迭代器 . 对于其他计划,例如动态,您必须以不同方式实现它们 . 请注意它's possible the parallel code and then sequential code don' t给出相同的结果,例如如果 (b-a)/step 有一个小数部分(但 (10.-0)/1. = 10. 没问题) . 因此,最好更改代码以使用整数迭代器是安全的 .

  • 2

    OpenMP要求循环变量为整数类型:

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

    循环结构的语法如下:#pragma omp for ...
    for循环
    ...具体来说,所有相关的for循环必须具有规范循环形式(参见第53页的第2.6节) . 3在进入最外层循环之前计算每个相关循环的迭代计数 . 如果任何关联循环的执行更改了用于计算任何迭代计数的任何值,则行为未指定 . 6用于计算折叠循环的迭代计数的整数类型(或类型,对于Fortran)是实现定义的 .

    你不能在openmp循环结构中使用浮点类型的变量 . 你的第一个循环有 i 整数,这是正确的,第二个循环有 float 类型的变量,这是不正确的 . 规范循环形式在"2.6 Canonical Loop Form" - http://www.openmp.org/wp-content/uploads/openmp-4.5.pdf#page=62中定义为

    for(init-expr; test-expr; incr-expr)结构化块
    ...
    var - 以下之一:
    *有符号或无符号整数类型的变量 .
    *对于C,随机访问迭代器类型的变量 .
    *对于C,指针类型的变量

    incr-expr以下之一:
    ...

    • var = incr

    incr循环不变整数表达式

    而你的第二个循环没有规范形式,也不能并行 .

    #pragma omp parallel for
    for(x[0]=0.000000; x[0]<10.000000; x[0]+=1.000000)
    

    使用var和incr的浮点值预先编译获得循环迭代计数是很困难的:一些十进制常数不能以浮点格式精确表示(例如,浮点数为0.2,为0f3FC999999999999A; 0.1为0.2多种语言的0.30000000000000004,请查看https://0.30000000000000004.com/) .

    你可以尝试整数数组或 long s或 long long

    #define MAX_DIMENSIONS  10
    
    long long  x[MAX_DIMENSIONS];
    unsigned int i,y=0;
    
    #pragma offload target(mic) in(x[MAX_DIMENSIONS],i,y)
    {
        #pragma omp parallel for
        for(x[0]=0; x[0] < 10; x[0] += 1)
            /* code here */
    }
    

    或者您可以尝试在循环之前估计浮点范围的正确循环计数,然后在并行循环中使用整数迭代器作为var和incr(确保进行正确的舍入) .

相关问题