Type with allocatables
Types with allocatables are handled differently by compilers when using OpenACC. In C this would be equivalent to a struct with a pointer inside. According to the OpenACC specification it should not be possbile to write a type with allocatables to the gpu in one go. However, we noticed that it worked sometimes and thus we have listed the differences here
OpenACC 3.3 section 2.6.4
When a data object is copied to device memory, the values are copied exactly. If the data is a data
structure that includes a pointer, or is just a pointer, the pointer value copied to device memory
will be the host pointer value. If the pointer target object is also allocated in or copied to device
memory, the pointer itself needs to be updated with the device address of the target object before
dereferencing the pointer in device memory
In the tables below, the Correctness column states whether each compiler's observed behaviour conforms to the OpenACC specification.
Container with "declare create"
Code
program main
implicit none
type container_type
real, dimension(:), allocatable :: values
end type
real, dimension(:) :: host_mem(2) = (/4,2/), res(2)
integer :: i
type(container_type) :: container
!$acc declare create(container)
allocate(container%values(2))
container%values = host_mem
write(*,*) "Checking if allocatable values are copied to device after declare create ..."
!$acc parallel loop
do i=1,2
res(i) = container%values(i)
enddo
write(*,*) "Success", res
end program
| Compiler |
Result |
Correctness |
Notes |
| Cray Fortran 19.0.0 |
❌ Crash |
Per spec — copying the container does not attach values |
Compiler warning (Variable "(?)" is used before it is defined); memory access fault at runtime. |
| nvfortran 25.3-0 |
❌ Crash |
Per spec — copying the container does not attach values |
No warning; CUDA_ERROR_ILLEGAL_ADDRESS at runtime. |
Container with "enter data"
Code with local variable
program main
use openacc
implicit none
type container_type
real, dimension(:), allocatable :: values
end type
real, dimension(:) :: host_mem(2) = (/4,2/), res(2)
integer :: i
type(container_type) :: container
!$acc enter data create(container)
allocate(container%values(2))
container%values = host_mem
write(*,*) "Checking if allocatable values are copied to device after enter data create ..."
!$acc parallel loop
do i=1,2
res(i) = container%values(i)
enddo
write(*,*) "Success", res
end program
| Compiler |
Result |
Correctness |
Notes |
| Cray Fortran 19.0.0 |
❌ Crash |
Per spec — values is never attached |
Memory access fault at runtime. |
| nvfortran 25.3-0 |
✅ OK |
Not per spec — relies on a non-portable automatic deep copy |
Prints Success 4.000000 2.000000. |
Code with module variable
module static
type container_type
real, dimension(:), allocatable :: values
end type
type(container_type) :: container
end module
program main
use static, only: container
implicit none
real, dimension(:) :: host_mem(2) = (/4,2/), res(2)
integer :: i
!$acc enter data create(container)
allocate(container%values(2))
container%values = host_mem
write(*,*) "Checking if allocatable values are copied to device after enter data create of a module variable ..."
!$acc parallel loop
do i=1,2
res(i) = container%values(i)
enddo
write(*,*) "Success", res
end program
| Compiler |
Result |
Correctness |
Notes |
| Cray Fortran 19.0.0 |
❌ Crash |
Per spec — values is never attached |
Memory access fault at runtime. |
| nvfortran 25.3-0 |
🟡 Wrong result |
Not per spec — relies on a non-portable automatic deep copy |
Prints Success 4.000000 0.000000; the second element should be 2.0. The module variable case silently produces an incorrect value. |
Code with enter data for member variable
program main
use openacc
implicit none
type container_type
real, dimension(:), allocatable :: values
end type
real, dimension(:) :: host_mem(2) = (/4,2/), res(2)
integer :: i
type(container_type) :: container
!$acc enter data create(container)
allocate(container%values(2))
!$acc enter data create(container%values)
container%values = host_mem
!$acc update device(container%values)
write(*,*) "Checking if allocatable values are copied to device after enter data create ..."
!$acc parallel loop
do i=1,2
res(i) = container%values(i)
enddo
write(*,*) "Success", res
end program
| Compiler |
Result |
Correctness |
Notes |
| Cray Fortran 19.0.0 |
✅ OK |
Per spec — values is allocated, explicitly attached, and copied with update device |
Prints Success 4. 2. (correct). |
| nvfortran 25.3-0 |
✅ OK |
Per spec — values is allocated, explicitly attached, and copied with update device |
Prints Success 4.000000 2.000000 (correct). |
Container with no data/declare statement
Code
program main
implicit none
type pointer_type
real, dimension(:), allocatable :: values
end type
real, dimension(:) :: host_mem(2) = (/4,2/), res(2)
integer :: i
type(pointer_type) :: indirect
allocate(indirect%values(2))
indirect%values = host_mem
write(*,*) "Checking if allocatable values are copied to device with !$acc parallel loop ..."
!$acc parallel loop
do i=1,2
res(i) = indirect%values(i)
enddo
write(*,*) "Success", res
end program
| Compiler |
Result |
Correctness |
Notes |
| Cray Fortran 19.0.0 |
❌ Crash |
Per spec — values is never attached |
No warning at compile time; memory access fault at runtime. |
| nvfortran 25.3-0 |
✅ OK |
Not per spec — relies on a non-portable automatic deep copy |
Prints Success 4.000000 2.000000. |