Intel® Fortran Compiler 18.0 Developer Guide and Reference
General Compiler Directive: Enables High Band Width (HBW) memory or non-HBW memory allocation for the lexically next ALLOCATE statement. This directive only applies to Intel® 64 architecture targeting the Intel® Xeon Phi™ product family x200 (formerly code name Knights Landing) and it is only available for Linux* systems.
!DIR$ MEMKIND : memory[, ALIGN:n ]
memory |
Specifies the requested memory kind. It must be one of the following:
|
n |
Is a positive integer constant expression. Its value must be a positive power of 2, that is, 1, 2, 4, 8, 16, etc, between 1 and 2097152 == 2**21 == 2MB on Linux*. It specifies the requested memory alignment in bytes for this allocation. |
This directive must be placed lexically immediately before an ALLOCATE statement (intervening comments and blank lines are allowed; statements and other directives are not allowed). The MEMKIND specified in this directive overrides any ATTRIBUTE MEMKIND that is associated with the object being allocated.
You can inquire about the memory allocation space of a variable using the FOR_GET_MEMKIND intrinsic function.
The following rules apply to deallocation of a variable:
If the variable has the ALLOCATABLE attribute, when it is deallocated the variable is reset to the MEMKIND setting in the current scope. That is, if the variable was explicitly declared with MEMKIND in the called routine (whether it’s local, host-associated or use-associated) then that MEMKIND setting is restored at the time of deallocation.
If the variable is a dummy argument and it is given the MEMKIND attribute in the called routine, the variable retains that MEMKIND setting on deallocation; otherwise, the variable is given MEMKIND setting DDR on deallocation.
If the variable has the POINTER attribute, the MEMKIND setting for the variable always reverts to DDR on deallocation.
The MEMKIND setting for a variable can be affected by statements other that ALLOCATE and DEALLOCATE:
MEMKIND and MOVE_ALLOC
Consider the statement:
MOVE_ALLOC (FROM, TO)
The definition of MOVE_ALLOC says that TO gets deallocated, then TO points to FROM’s data, finally FROM is marked deallocated. The MEMKIND setting of FROM is copied to TO, and then the MEMKIND setting of FROM is changed according to the deallocation rules above.
MEMKIND and ALLOCATE(SOURCE=) or ALLOCATE(MOLD=)
If the ALLOCATE statement contains either a SOURCE= or a MOLD= clause, the MEMKIND setting of the source (or mold) is not significant. The new object being allocated takes its MEMKIND setting either from a directive preceding this ALLOCATE statement or from the MEMKIND ATTRIBUTE, if any, of the object being allocated.
MEMKIND and reallocation of the left-hand side of an assignment
The allocatable object on the left-hand side of an assignment will have the same MEMKIND setting as it had before it was reallocated.
In the following example, various allocations and deallocations show how MEMKIND is handled.
USE IFCORE
REAL, ALLOCATABLE :: R(:)
!DIR$ ATTRIBUTES MEMKIND:HBW :: R
ALLOCATE(R(100))
PRINT *, FOR_GET_MEMKIND® ! prints 1 for HBW
CALL DEALLOCME® ! MEMKIND of R was changed by DEALLOCME
PRINT *, FOR_GET_MEMKIND® ! prints 0 for DDR
CALL REALLOCME_HBW® ! MEMKIND of R is still HBW
print *, for_get_memkind(r) ! prints 1 for HBW
!DIR$ MEMKIND:DDR, ALIGN:32
ALLOCATE(R(1000)) ! Allocated in DDR, 32-byte aligned
PRINT *, FOR_GET_MEMKIND® ! prints 0 for DDR
DEALLOCATE® ! MEMKIND reverted to HBW, as declared
PRINT *, FOR_GET_MEMKIND® ! prints 1 for HBW
CALL REALLOCME® ! MEMKIND of R is HBW at entrance
PRINT *, for_get_memkind® ! prints 1 for HBW
CONTAINS
SUBROUTINE DEALLOCME(X)
REAL, ALLOCATABLE :: X(:)
DEALLOCATE (X) ! No attribute on the dummy; revert to DDR
END SUBROUTINE DEALLOCME
SUBROUTINE REALLOCME(X)
REAL, ALLOCATABLE :: X(:)
ALLOCATE(X(100)) ! Use MEMKIND from the actual argument
END SUBROUTINE REALLOCME
SUBROUTINE REALLOCME¬_HBW(X)
REAL, ALLOCATABLE :: X(:)
!DIR$ ATTRIBUTES MEMKIND:HBW :: X
ALLOCATE(X(100)) ! Use MEMKIND specified on dummy argument
END SUBROUTINE REALLOCME
END
In the following example, allocations and deallocations of pointers are simpler; their MEMKIND always reverts to DDR:
REAL, POINTER :: PR(:) ! MEMKIND always starts as DDR
print *, for_get_memkind(pr) ! prints 0 for DDR
!DIR$ MEMKIND:HBW
ALLOCATE(PR(100)) ! Allocate in HBW memory
PRINT *, FOR_GET_MEMKIND(PR) ! prints 1 for HBW
DEALLOCATE(PR) ! Resets MEMKIND to DDR
PRINT *, FOR_GET_MEMKIND(PR) ! prints 0 for DDR
ALLOCATE(PR(55)) ! Allocated in DDR
PRINT *, FOR_GET_MEMKIND(PR) ! prints 0 for DDR
END