OpenACC: сложный цикл несет зависимость от '* (* (b))' предотвращает распараллеливание

Я использую OpenACC с динамическим распределением массивов. Вот как я распределяю:

float **a;
float **b;
float **c;
float **seq;
a=(float**)malloc(SIZE*sizeof(float*));
b=(float**)malloc(SIZE*sizeof(float*));
c=(float**)malloc(SIZE*sizeof(float*));
seq=(float**)malloc(SIZE*sizeof(float*));
for(i=0; i<SIZE; i++){
        a[i]=(float*)malloc(SIZE*sizeof(float));
        b[i]=(float*)malloc(SIZE*sizeof(float));
        c[i]=(float*)malloc(SIZE*sizeof(float));
        seq[i]=(float*)malloc(SIZE*sizeof(float));
}

и вот как я параллельно добавляю матрицу:

#pragma acc kernels copyin(a[0:SIZE][0:SIZE],b[0:SIZE][0:SIZE]) copy(c[0:SIZE][0:SIZE])
        for (i = 0; i < SIZE; ++i) {
                for (j = 0; j < SIZE; ++j) {
                        c[i][j] = a[i][j] + b[i][j];
                }
        }

Когда я компилирую этот код с pgcc, он обнаруживает зависимость от float** указателей по итерациям цикла и генерирует все скалярное ядро ​​(1 блок 1 поток на блок), которое работает плохо, как ожидалось:

 40, Complex loop carried dependence of '*(*(b))' prevents parallelization
     Complex loop carried dependence of '*(*(a))' prevents parallelization
     Complex loop carried dependence of '*(*(c))' prevents parallelization
     Accelerator scalar kernel generated
     CC 1.0 : 11 registers; 40 shared, 4 constant, 0 local memory bytes
     CC 2.0 : 22 registers; 0 shared, 56 constant, 0 local memory bytes

Цикл, очевидно, параллельный, и я думаю, что это тоже может обнаружить компилятор. Мне любопытно, как это объяснить pgcc?

Заранее спасибо.


person lashgar    schedule 16.10.2012    source источник
comment
Это может быть не связано с вашим вопросом, но, НАВСЕГДА, вам следует избегать структур с плавающей запятой **. Float ** не являются смежными в памяти, и я не знаю, как в этом случае будет работать копирование. Вы можете просто выделить свою 2D-матрицу как одномерный массив и [i] [j] == a [i + SIZE * j]. Надеюсь это поможет.   -  person leo    schedule 17.10.2012
comment
Вы определенно правы! Конечно, поможет! Спасибо.   -  person lashgar    schedule 17.10.2012


Ответы (1)


Думаю, я нашел ответ. Ключ в том, чтобы использовать предложение independent:

    #pragma acc data copyin(a[0:SIZE][0:SIZE],b[0:SIZE][0:SIZE]) copy(c[0:SIZE][0:SIZE])
    {
             # pragma acc region 
             {
                    #pragma acc loop independent vector(16)
                    for (i = 0; i < SIZE; ++i) {
                            #pragma acc loop independent vector(16)
                            for (j = 0; j < SIZE; ++j) {
                                   c[i][j] = a[i][j] + b[i][j];
                            }
                    }
             }
    }
person lashgar    schedule 16.10.2012
comment
Вы также должны иметь возможность использовать ключевое слово restrict в объявлениях a, b, c (вероятно, требуется только на c) для достижения того же эффекта. - person Robert Crovella; 16.10.2012
comment
@RobertCrovella Спасибо! Я протестировал его, как вы предлагаете, и цикл распараллеливается, как и ожидалось. Похоже, что в этой небольшой выборке они работают одинаково. - person lashgar; 16.10.2012
comment
что означает vector(16)? - person anupshrestha; 24.08.2015
comment
@anup vector(16) указывает компилятору использовать векторы шириной 16 для выполнения цикла. Например, если компилятор компилирует OpenACC для устройств с поддержкой CUDA, компилятор может использовать 16 потоков в измерении блока потока. - person lashgar; 25.08.2015