cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: FFTW 3.3.8: Allocating aligned memory in Fortran cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: cannam@167:
cannam@167:

cannam@167: Next: , Previous: , Up: Calling FFTW from Modern Fortran   [Contents][Index]

cannam@167:
cannam@167:
cannam@167: cannam@167:

7.5 Allocating aligned memory in Fortran

cannam@167: cannam@167: cannam@167: cannam@167: cannam@167:

In order to obtain maximum performance in FFTW, you should store your cannam@167: data in arrays that have been specially aligned in memory (see SIMD alignment and fftw_malloc). Enforcing alignment also permits you to cannam@167: 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 cannam@167: arrays. Unfortunately, standard Fortran arrays do not provide cannam@167: any alignment guarantees. The only way to allocate aligned cannam@167: memory in standard Fortran is to allocate it with an external C cannam@167: function, like the fftw_alloc_real and cannam@167: fftw_alloc_complex functions. Fortunately, Fortran 2003 provides cannam@167: a simple way to associate such allocated memory with a standard Fortran cannam@167: array pointer that you can then use normally. cannam@167:

cannam@167:

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

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

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

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

and here is an L × M × N cannam@167: 3d complex array: cannam@167:

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

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

cannam@167:
cannam@167:
cannam@167:

cannam@167: Next: , Previous: , Up: Calling FFTW from Modern Fortran   [Contents][Index]

cannam@167:
cannam@167: cannam@167: cannam@167: cannam@167: cannam@167: