The Map Clause
As we have seen in the first topic of this roadmap, the target directive automatically manages all variables accessed in the region. So why do we need the map clause? By default, the target directive copies all non-scalar variables within the lexical extent of the target region to the device on entry and back to the host on exit, while treating all scalars as firstprivate (each thread receives a private copy that is not copied back). This is convenient for most cases, but it can create unnecessary copies in certain scenarios where copying back and forth is wasteful. The map clause allows finer control over data transfer between the host and the device by specifying which variables to transfer and in which direction.
map(map-type: variables)
| Map-type | Behavior |
|---|---|
to |
Allocate on device, copy from host to device on entry, deallocate on exit |
from |
Allocate on device, copy from device to host on exit, deallocate on exit |
tofrom |
Allocate on device, copy both directions, deallocate on exit |
alloc |
Allocate on device only, no copy, deallocate on exit |
If map-type is not specified (e.g. map(x)), the default map-type is tofrom.
Before a variable is mapped to the device, the runtime checks if the variable is already present on the device. If it is, the mapping is skipped. However, if the always map-type modifier is used (e.g. map(always, tofrom: x)), the variable will always be copied even if it is already present on the device.
Data Mapping with default tofrom
In the following example, the map clause is used without specifying a map-type. Since the default map-type is tofrom, all listed variables are copied to the device on entry and back to the host on exit.
More Efficient Data Mapping with specific map-types
By specifying map(to:) or map(from:), you can avoid unnecessary copies in either direction:
CVW material development is supported by NSF OAC awards 1854828, 2321040, 2323116 (UT Austin) and 2005506 (Indiana University)