Skip to content

1. A first device array ​

The heat solver starts with a temperature field of 8 cells: room temperature with a hot spot in the middle. Before any kernel, the field must get to the device and back. Every FUNDAL program follows the same steps: initialize the device, allocate device memory, copy to and from it, free it.

fortran
program heat_1
!< Tutorial, chapter 1: a first device array.
use, intrinsic :: iso_fortran_env, only : I4P=>int32, I8P=>int64, R8P=>real64
use            :: fundal
implicit none
integer(I4P), parameter :: n=8              ! number of cells
real(R8P), pointer      :: t_dev(:)=>null() ! temperature, on the device
real(R8P)               :: t(n)             ! temperature, on the host
integer(I8P)            :: allocs           ! live device allocations
integer(I4P)            :: ierr             ! error status

call dev_init
call dev_alloc(fptr_dev=t_dev, ubounds=[n], ierr=ierr, label='temperature')
if (ierr /= 0) error stop 'device allocation failed'
t = 20._R8P                                   ! room temperature...
t(n/2) = 100._R8P                             ! ...with a hot spot
call dev_memcpy_to_device(dst=t_dev, src=t)   ! host -> device
t = 0._R8P                                    ! forget the host copy
call dev_memcpy_from_device(dst=t, src=t_dev) ! device -> host
print '(A,*(F6.1))', 'temperature:', t
call dev_free(t_dev)
call dev_get_alloc_stats(allocs=allocs)
print '(A,I0)', 'live device allocations: ', allocs
endprogram heat_1
  • dev_init selects the device and sets the global variables that describe it (mydev, devs_number, ...). Call it once, before any other FUNDAL call.
  • dev_alloc allocates n reals on the device and associates the pointer t_dev with them. Device arrays are always pointers, declared =>null(). ierr is not optional: a non-zero value means the allocation failed (FUNDAL_ERR_FPTR_DEV_NOT_ALLOCATED) and t_dev is null. The label names the allocation in leak reports (chapter 7).
  • dev_memcpy_to_device and dev_memcpy_from_device copy whole arrays; the arguments are always dst then src.
  • dev_free releases the device memory and nullifies the pointer; dev_get_alloc_stats counts the live device allocations: zero at the end means nothing leaked.

The kinds come from iso_fortran_env: FUNDAL does not export kind parameters, so that its names cannot clash with those of your code (PENF, for example, has its own I4P and R8P).

Running it ​

text
$ heat_1
temperature:  20.0  20.0  20.0 100.0  20.0  20.0  20.0  20.0
live device allocations: 0

The hot spot made the round trip. On the host nothing distinguishes t_dev from a host array; on a GPU, reading t_dev(i) outside a kernel reads a device address from the host, which is an error.

Device pointers on the host

A pointer returned by dev_alloc may be passed to FUNDAL and inquired (lbound, ubound, size) on the host, but its elements must be read and written only inside kernels or through the copy routines.

What you learned

The four steps dev_init, dev_alloc, dev_memcpy_*, dev_free; device arrays as pointers; ierr and the allocation statistics. Reference: Structured memory, Initialization and devices.

Next: 2. Bounds, resizing, copies.