In the code that follows, I have a set of nested loops. The outer loop is the one I’d like to parallelize on the GPU with OpenACC. The inner loop should be run sequentially by each individual thread.
When I try to compile this code using
pgfortran -o inf_while_test.exe -acc -ta=nvidia -Minfo=accel -Minline=levels:10 inf_while_test.f90
I get the following output:
PGF90-W-0155-Accelerator region ignored; see -Minfo messages (inf_while_test.f90: 63)
inf_while_test:
63, Accelerator region ignored
65, Accelerator restriction: function/procedure calls are not supported
71, Accelerator restriction: unsupported call to ‘kiss’
The line number being flagged, 71, isn’t even the first occurrence of a call to kiss in the program. What is going on here, and what am I doing incorrectly?
OpenACC will allow do while(true) loops; I have tested this. There’s apparently something about this more complicated structure that’s throwing the compiler for a loop, so to speak.
Code follows:
!--------------------------------------------------------------------
module marsaglia
implicit none
private
public :: kiss, kisset
INTEGER :: x=123456789, y=362436069, z=521288629, w=916191069
contains
subroutine kiss(rand_out)
integer :: i
real :: rand_out
! The KISS (Keep It Simple Stupid) random number generator.
! http://www.fortran.com/kiss.f90 . Slightly modified.
do while(.true.)
x = 69069 * x + 1327217885
y = m (m (m (y, 13), - 17), 5)
z = 18000 * iand (z, 65535) + ishft (z, - 16)
w = 30903 * iand (w, 65535) + ishft (w, - 16)
i = x + y + ishft (z, 16) + w
rand_out = i*2.33e-10 + 0.5
if((rand_out .gt. 0.) .and. (rand_out .lt. 1.)) return
enddo
contains
function m(k, n)
integer :: m, k, n
m = ieor (k, ishft (k, n) )
end function m
end subroutine
function kisset (ix, iy, iz, iw)
integer :: kisset, ix, iy, iz, iw
x = ix
y = iy
z = iz
w = iw
kisset = 1
end function kisset
end module marsaglia
!--------------------------------------------------------------------
!=====================
program inf_while_test
use marsaglia
implicit none
integer :: i, imax, iseed
integer, dimension(8) :: time_array
real :: temp, rand, start_time, end_time, ran4
iseed = -2255
i = kisset(iseed, 2*iseed, 3*iseed, 4*iseed)
imax = 20000
call date_and_time(values=time_array)
start_time = time_array(5)*3600 + time_array(6)*60 + &!&
time_array(7) + 0.001*time_array(8)
!$acc kernels loop private(i)
outer_loop: do i = 1, imax
inner_loop: do while(.true.)
call kiss(rand)
if(rand .gt. 0.99) then
exit inner_loop
endif
call kiss(rand)
if(rand .lt. 0.9) then
temp = rand
else
call kiss(rand)
temp = rand * 3.14159d0
endif
enddo inner_loop
enddo outer_loop
!$acc end kernels
call date_and_time(values=time_array)
end_time = time_array(5)*3600 + time_array(6)*60 + &!&
time_array(7) + 0.001*time_array(8)
print *, "time = ",end_time - start_time
end program inf_while_test
!=========================