#fortran #gpu #openacc #pgi
#fortran #графический процессор #openacc #pgi
Вопрос:
Я пытаюсь использовать рабочий частный массив с OpenACC, но я продолжаю получать неправильные результаты. Я предполагаю, что происходит какая-то проблема с состоянием гонки, но я не могу найти где.
Я использую компилятор PGI (18.10, OpenPOWER) и компилирую с :
pgf90 -gopt -O3 -Minfo=all -Mcuda=ptxinfo -acc -ta=tesla:cc35 main.F90
Вот минимальный пример того, чего я пытаюсь достичь:
#define lx 7000
#define ly 500
program test
implicit none
integer :: tmp(ly,1), a(lx,ly), b(lx,ly)
integer :: x,y,i
do x=1,lx
do y=1,ly
a(x,y) = x y
end do
end do
!$acc parallel num_gangs(1)
!$acc loop worker private(tmp)
do x=1,lx
!$acc loop vector
do y=1,ly
tmp(y,1) = -a(x,y)
end do
!$acc loop vector
do y=1,ly
b(x,y) = -tmp(y,1)
end do
end do
!$acc end parallel
print *, "check"
do x=1,lx
do y=1,ly
if(b(x,y) /= x y) print *, x, y, b(x,y), x y
end do
end do
print*, "end"
end program
Я ожидал получить b == a, но это не так.
Пожалуйста, обратите внимание, что я определил, tmp(ly,1)
потому что я получаю ожидаемый результат, когда я определяю tmp(ly)
как одномерный массив. Даже если оно работает с одномерным массивом, я не уверен, что оно полностью соответствует стандарту OpenACC.
Я что-то здесь упускаю?
РЕДАКТИРОВАТЬ: Последний цикл проверяет, является ли a ==b, и выводит неправильные значения. Ожидаемый результат (который я получаю при отключенном OpenACC) является :
check
end
То, что я получаю с включенным OpenACC, выглядит примерно так (изменяется между запусками):
check
1 1 5 2
1 2 6 3
1 3 7 4
[...]
end
Ответ №1:
Похоже на проблему компилятора, когда «tmp» совместно используется рабочими вместо того, чтобы каждый рабочий получал личную копию. Это, в свою очередь, вызывает состояние гонки в вашем коде.
Я отправил отчет о проблеме в PGI (TPR # 27025) и отправил его нашим инженерам для дальнейшего расследования.
Обходной путь заключается в использовании «gang» вместо «worker» во внешнем цикле или, как вы заметили, сделать «tmp» в виде массива одного измерения.
Обновление: TPR # 27025 был исправлен в выпуске PGI 19.7.
Комментарии:
1. Где я могу следить за ходом выполнения того отчета о проблеме, который вы отправили?
2. У нас нет общедоступного средства отслеживания ошибок. Для получения статуса вы можете отправить электронное письмо в службу поддержки клиентов PGI по адресу trs@ pgroup, com.
Ответ №2:
Эти два acc loop
!$acc loop vector
do y=1,ly
tmp(y,1) = -a(x,y)
end do
!$acc loop vector
do y=1,ly
b(x,y) = -tmp(y,1)
end do
одновременно будет выполняться на графическом процессоре. То есть они выполняются параллельно. Чтобы гарантировать, что tmp
предполагается исправить значения в первом цикле, прежде чем оно будет использовано во втором цикле, они должны быть в другой acc parallel
конструкции.
Правильный код будет выглядеть следующим образом:
do x=1,lx
!$acc parallel loop
do y=1,ly
tmp(y,1) = -a(x,y)
end do
!$acc parallel loop
do y=1,ly
b(x,y) = -tmp(y,1)
end do
end do