Почему следующий код:OpenACC суммы при каждом выполнении
#include <iostream>
int main(int argc, char const *argv[])
{
int sum = 0;
int *array;
array = new int [100];
#pragma acc enter data create(array[0:100],sum)
#pragma acc parallel loop present(array[0:100])
for (int i = 0; i < 100; ++i)
{
array[i] = 1;
}
#pragma acc parallel loop present(array[0:100],sum) reduction(+:sum)
for (int i = 0; i < 100; ++i)
{
sum += array[i];
}
#pragma acc exit data delete(array[0:100]) copyout(sum)
std::cout << sum << std::endl;
return 0;
}
различных результатах при каждом выполнении?
$ pgcpp -acc -Minfo main.cpp
main:
7, Generating enter data create(sum)
Generating enter data create(array[:100])
Generating present(array[:100])
Accelerator kernel generated
12, #pragma acc loop gang, vector(256) /* blockIdx.x threadIdx.x */
7, Generating Tesla code
15, Generating present(array[:100])
Generating present(sum)
Accelerator kernel generated
18, #pragma acc loop gang, vector(256) /* blockIdx.x threadIdx.x */
20, Sum reduction generated for sum
15, Generating Tesla code
25, Generating exit data copyout(sum)
Generating exit data delete(array[:100])
$ ./a.out
100
$ ./a.out
200
$ ./a.out
300
$ ./a.out
400
В соответствии со стандартом OpenACC:
В директиве данных на выходе, данные копируются обратно в локальную память и высвобождены.
Казалось бы, что sum
является не перераспределена и вместо используемых повторно (и увеличивается) при каждом запуске программы. Кроме того, оператор +
в директиве reduction
инициализирует редукционную переменную до 0
, поэтому этого не должно произойти, даже если sum
не были освобождены между выполнением.
я могу избежать этого либо с помощью copyin
вместо create
для sum
в enter data
директивы или установить sum = 0
в одной банде, один рабочий ядро:
#pragma acc parallel present(sum) num_gangs(1) num_workers(1)
sum = 0;
Но это не является удовлетворительным, поскольку она требует либо дорогостоящий хост для копирования данных устройства, либо запуск ядра. Почему моя программа ведет себя так?
Спасибо за освобождение. Я полагаю, что не случайно, что местоположение 'sum' на памяти устройства всегда одно и то же во всех исполнениях и показывает что-то о реализации компилятора (PGI) стандартов OpenACC? – lodhb
Я не знаю, что он раскрывает.Я могу сделать то же самое с обычным кодом CUDA (у вас есть неинициализированная переменная устройства, распределенная в том же месте от запуска до запуска). Если вы будете запускать один и тот же код несколько раз, разве вы не ожидаете, что он будет вести себя одинаково? Это может включать расположение распределения. –
Я не знаком со стандартным поведением компилятора/ОС для выделения памяти и предполагал, что данная переменная не всегда распределяется в том же месте в памяти. – lodhb