ARR03-F. Specify array bounds when copying data to device memory
Programmers shall explicitly specify array bounds or ranges when transferring data between host and device memory. This ensures sufficient memory is mapped and prevents undefined behavior.
In heterogeneous computing environments (e.g., using GPUs or other accelerators), arrays often must be explicitly moved from host to device. Omitting bounds can introduce several risks:
- Insufficient data transfer: For assumed-size or partially known arrays, the compiler may copy too few elements, causing undefined behavior on the device.
- Excessive data transfer: Copying the entire array when only a section is needed degrades performance.
- Memory violations: Incorrect bounds may cause out-of-bounds access on the device, leading to illegal memory access or silent data corruption.
Programmers should not rely on compiler defaults, as optimizations may assume that out-of-bounds behavior does not occur, potentially bypassing safety checks.
Noncompliant Code Example
In this noncompliant example, a large array data_buffer is used to store simulation results, but only a portion of it (defined by n ) is valid. The directive !$omp target data attempts to map the entire array to the device (e.g. GPU). This is inefficient and potentially dangerous if the entire buffer has not been appropriately initialized or allocated for the device's memory limits.
program device_transfer
use iso_fortran_env, only: real64
implicit none
integer, parameter :: max_size = 100000
real(real64), allocatable :: data_buffer(:)
integer, parameter :: n = 1000
integer :: i
allocate(data_buffer(max_size))
data_buffer(1:n) = [(real(i, real64), i = 1, n)]
! Noncompliant: Maps the entire buffer instead of the actual used range (n elements)
!$omp target map(to: data_buffer)
! Accelerator operations here
!$omp end
end program
Compliant Solution
In this compliant solution, the programmer uses an array section to specify the exact bounds of the data to be transferred. This ensures that only the required memory is mapped to the device, providing enough storage for objects while avoiding the ambiguity of undefined behavior.
program device_transfer
use iso_fortran_env, only: real64
implicit none
integer, parameter :: max_size = 100000
real(real64), allocatable :: data_buffer(:)
integer, parameter :: n = 1000
integer :: i
allocate(data_buffer(max_size))
data_buffer(1:n) = [(real(i, real64), i = 1, n)]
! Compliant: Explicitly specifies the range for the transfer
!$omp target map(to: data_buffer(1:n))
! Accelerator operations here
!$omp end target
end program
Risk Assessment
Failure to specify array bounds when mapping data to a device can lead to memory corruption on the accelerator, performance bottlenecks, or program termination.
| Recommendation | Severity | Likelihood | Detectable | Repairable | Priority | Level |
| ARR03-F | High | Probable | No | Yes | P27 | L1 |
Attachments:
button_arrow_left.png (image/png)
button_arrow_up.png (image/png)
button_arrow_right.png (image/png)


