使用 C++ 编译器构建的 OpenAcc 程序比 C 构建版本慢得多

问题描述 投票:0回答:1

我正在处理的代码是用 C++ 编写的,有点复杂,但下面的示例显示了问题。它来自 Chandrasekaran 和 Juckeland 所著的一本书。如果使用 nvc -acc(或 pgcc -acc,如作者所做的那样)编译并运行,则需要几秒钟才能完成。如果我使用 nvc++ -acc (pgc++ -acc),它会慢几个数量级,甚至比串行版本更慢。我很好奇是否有人注意到类似的问题或知道可能的解释。

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#define WIDTH 1000
#define HEIGHT 1000
#define TEMP_TOLERANCE 0.01
double Temperature[HEIGHT+2][WIDTH+2];
double Temperature_previous[HEIGHT+2][WIDTH+2];
void initialize();
void track_progress(int iter);

int main(int argc, char *argv[]) {
    int i, j;
    int iteration=1;
    double worst_dt=100;
    struct timeval start_time, stop_time, elapsed_time;
    gettimeofday(&start_time,NULL);
    initialize();

#pragma acc data copy(Temperature_previous), create(Temperature)    
{
    while ( worst_dt > TEMP_TOLERANCE ) {

#pragma acc kernels
        for(i = 1; i <= HEIGHT; i++) {
            for(j = 1; j <= WIDTH; j++) {
                Temperature[i][j] = 0.25 * (Temperature_previous[i+1][j]
                        + Temperature_previous[i-1][j]
                        + Temperature_previous[i][j+1]
                        + Temperature_previous[i][j-1]);
            }
        }
        worst_dt = 0.0;

#pragma acc kernels 
        for(i = 1; i <= HEIGHT; i++){
            for(j = 1; j <= WIDTH; j++){
                worst_dt = fmax( fabs(Temperature[i][j]-
                            Temperature_previous[i][j]),worst_dt);
                Temperature_previous[i][j] = Temperature[i][j];
            }
        }

        if((iteration % 100) == 0) {
#pragma acc update host(Temperature)
            track_progress(iteration);
        }
        iteration++;
    }
}

    gettimeofday(&stop_time,NULL);
    timersub(&stop_time, &start_time, &elapsed_time);
    printf("\nMax error at iteration %d was %f\n",
            iteration-1, worst_dt);
    printf("Total time was %f seconds.\n",
            elapsed_time.tv_sec+elapsed_time.tv_usec/1000000.0);
}
void initialize(){
    int i,j;
    for(i = 0; i <= HEIGHT+1; i++){
        for (j = 0; j <= WIDTH+1; j++){
            Temperature_previous[i][j] = 0.0;
        }
    }
    for(i = 0; i <= HEIGHT+1; i++) {
        Temperature_previous[i][0] = 0.0;
        Temperature_previous[i][WIDTH+1] = (100.0/HEIGHT)*i;
    }
    for(j = 0; j <= WIDTH+1; j++) {
        Temperature_previous[0][j] = 0.0;
        Temperature_previous[HEIGHT+1][j] = (100.0/WIDTH)*j;
    }
}
void track_progress(int iteration) {
    int i;
    printf("---------- Iteration number: %d ------------\n",
            iteration);
    for(i = HEIGHT-5; i <= HEIGHT; i++) {
        printf("[%d,%d]: %5.2f ", i, i, Temperature[i][i]);
    }
    printf("\n");
}

我在两台Linux机器上测试了它,结果相同。我尝试了各种编译器,但只要我按照 C++ 标准而不是 C 进行编译,问题仍然存在。 -Minfo=all 没有显示任何定性意义。

performance gpu compiler-optimization openacc
1个回答
0
投票

我看到了同样的事情,如果您将

-Minfo=accel
添加到命令行中,您会看到它在第 37 行停止并行化循环,表示稍后需要最坏的_dt 值,从而导致依赖性。我不知道为什么编译器分析在这里无法正常工作,但是如果将第 36 行更改为以下内容,您将获得性能恢复:
#pragma acc kernels loop independent collapse(2) reduction(max:worst_dt)
。我会确保其中一位编译器人员能够看到这一点。

更新: 您还可以尝试将

-std=c++11
-std=c++14
添加到编译中,无需修改代码即可获得预期的性能。我不完全确定为什么默认标准存在此问题,但编译器团队已意识到此交换。

© www.soinside.com 2019 - 2024. All rights reserved.