Dear all,
Please see this Fortran code and output.
program scalar_array_multiplication
implicit none
integer, parameter :: n = 10
integer :: i
real :: array(n)
do i = 1, n
array(i) = i
end do
print *, 'Original array:'
print *, array
call multiply_array(array, 2.0)
print *, 'Updated array after multiplication:'
print *, array
contains
subroutine multiply_array(arr, scalar)
implicit none
real, intent(inout) :: arr(:)
real, intent(in), optional :: scalar
integer :: i
!$acc enter data copyin(arr)
!$acc parallel loop default(present)
do i=1,size(arr)
arr(i) = arr(i)*scalar
end do
!$acc exit data copyout(arr)
end subroutine multiply_array
!!
!! safe way of doing this
!!
!subroutine multiply_array(arr, scalar)
! implicit none
! real, intent(inout) :: arr(:)
! real, intent(in), optional :: scalar
! real :: factor
! integer :: i
! if (present(scalar)) then
! factor = scalar
! else
! factor = 1.0
! end if
! !$acc enter data copyin(arr)
! !$acc parallel loop default(present)
! do i = 1, size(arr)
! arr(i) = arr(i) * factor
! end do
! !$acc exit data copyout(arr)
!end subroutine multiply_array
end program scalar_array_multiplication
$ nvfortran --version && nvfortran -acc test.f90 -o test && ./test
nvfortran 24.3-0 64-bit target on x86-64 Linux -tp cascadelake
NVIDIA Compilers and Tools
Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
Original array:
1.000000 2.000000 3.000000 4.000000
5.000000 6.000000 7.000000 8.000000
9.000000 10.00000
hostptr=0x4030d8,eltsize=4,name=scalar,flags=0x20000200=present+implicit,async=-1,threadid=1
Present table dump for device[1]: NVIDIA Tesla GPU 0, compute capability 8.6, threadid=1
Hint: specify 0x800 bit in NV_ACC_DEBUG for verbose info.
host:0x407550 device:0x781b192fa000 size:40 presentcount:0+1 line:20 name:arr(:)
allocated block device:0x781b192fa000 size:512 thread:1
FATAL ERROR: data in PRESENT clause was not found on device 1: name=scalar host:0x4030d8
file:/home/pedro/Desktop/test.f90 multiply_array line:21
(The workaround, and generally the safe way of working with optional arguments, is in the commented subroutine)
I’m not sure if this is an expected behavior of default(present)
, for firstprivate
scalar arguments that are passed as an optional argument in a Fortran subroutine where present(scalar)
is .true.
. From the OpenACC Specification, I think there may be undefined behavior if present(scalar)
is .false.
. See section 2.17 here: https://www.openacc.org/sites/default/files/inline-images/Specification/OpenACC-3.2-final.pdf#page=86.62