Chris@19: Chris@19: Chris@19: Allocating aligned memory in Fortran - FFTW 3.3.4 Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19: Chris@19:
Chris@19: Chris@19:

Chris@19: Next: , Chris@19: Previous: Plan execution in Fortran, Chris@19: Up: Calling FFTW from Modern Fortran Chris@19:


Chris@19:
Chris@19: Chris@19:

7.5 Allocating aligned memory in Fortran

Chris@19: Chris@19:

In order to obtain maximum performance in FFTW, you should store your Chris@19: data in arrays that have been specially aligned in memory (see SIMD alignment and fftw_malloc). Enforcing alignment also permits you to Chris@19: safely use the new-array execute functions (see New-array Execute Functions) to apply a given plan to more than one pair of in/out Chris@19: arrays. Unfortunately, standard Fortran arrays do not provide Chris@19: any alignment guarantees. The only way to allocate aligned Chris@19: memory in standard Fortran is to allocate it with an external C Chris@19: function, like the fftw_alloc_real and Chris@19: fftw_alloc_complex functions. Fortunately, Fortran 2003 provides Chris@19: a simple way to associate such allocated memory with a standard Fortran Chris@19: array pointer that you can then use normally. Chris@19: Chris@19:

We therefore recommend allocating all your input/output arrays using Chris@19: the following technique: Chris@19: Chris@19:

    Chris@19: Chris@19:
  1. Declare a pointer, arr, to your array of the desired type Chris@19: and dimensions. For example, real(C_DOUBLE), pointer :: a(:,:) Chris@19: for a 2d real array, or complex(C_DOUBLE_COMPLEX), pointer :: Chris@19: a(:,:,:) for a 3d complex array. Chris@19: Chris@19:
  2. The number of elements to allocate must be an Chris@19: integer(C_SIZE_T). You can either declare a variable of this Chris@19: type, e.g. integer(C_SIZE_T) :: sz, to store the number of Chris@19: elements to allocate, or you can use the int(..., C_SIZE_T) Chris@19: intrinsic function. e.g. set sz = L * M * N or use Chris@19: int(L * M * N, C_SIZE_T) for an L × M × N array. Chris@19: Chris@19:
  3. Declare a type(C_PTR) :: p to hold the return value from Chris@19: FFTW's allocation routine. Set p = fftw_alloc_real(sz) for a real array, or p = fftw_alloc_complex(sz) for a complex array. Chris@19: Chris@19:
  4. Associate your pointer arr with the allocated memory p Chris@19: using the standard c_f_pointer subroutine: call Chris@19: c_f_pointer(p, arr, [...dimensions...]), where Chris@19: [...dimensions...]) are an array of the dimensions of the array Chris@19: (in the usual Fortran order). e.g. call c_f_pointer(p, arr, Chris@19: [L,M,N]) for an L × M × N array. (Alternatively, you can Chris@19: omit the dimensions argument if you specified the shape explicitly Chris@19: when declaring arr.) You can now use arr as a usual Chris@19: multidimensional array. Chris@19: Chris@19:
  5. When you are done using the array, deallocate the memory by call Chris@19: fftw_free(p) on p. Chris@19: Chris@19:
Chris@19: Chris@19:

For example, here is how we would allocate an L × M 2d real array: Chris@19: Chris@19:

       real(C_DOUBLE), pointer :: arr(:,:)
Chris@19:        type(C_PTR) :: p
Chris@19:        p = fftw_alloc_real(int(L * M, C_SIZE_T))
Chris@19:        call c_f_pointer(p, arr, [L,M])
Chris@19:        ...use arr and arr(i,j) as usual...
Chris@19:        call fftw_free(p)
Chris@19: 
Chris@19:

and here is an L × M × N 3d complex array: Chris@19: Chris@19:

       complex(C_DOUBLE_COMPLEX), pointer :: arr(:,:,:)
Chris@19:        type(C_PTR) :: p
Chris@19:        p = fftw_alloc_complex(int(L * M * N, C_SIZE_T))
Chris@19:        call c_f_pointer(p, arr, [L,M,N])
Chris@19:        ...use arr and arr(i,j,k) as usual...
Chris@19:        call fftw_free(p)
Chris@19: 
Chris@19:

See Reversing array dimensions for an example allocating a Chris@19: single array and associating both real and complex array pointers with Chris@19: it, for in-place real-to-complex transforms. Chris@19: Chris@19: Chris@19: Chris@19: