%\pagebreak \section{\kcode{target data} Construct} \label{sec:target_data} \subsection{Simple \kcode{target data} Construct} \label{subsec:target_data_simple} \index{constructs!target data@\kcode{target data}} \index{target data construct@\kcode{target data} construct} This example shows how the \kcode{target data} construct maps variables to a device data environment. The \kcode{target data} construct creates a new device data environment and maps the variables \ucode{v1}, \ucode{v2}, and \ucode{p} to the new device data environment. The \kcode{target} construct enclosed in the \kcode{target data} region creates a new device data environment, which inherits the variables \ucode{v1}, \ucode{v2}, and \ucode{p} from the enclosing device data environment. The variable \ucode{N} is mapped into the new device data environment from the encountering task's data environment. \cexample[4.0]{target_data}{1} \pagebreak The Fortran code passes a reference and specifies the extent of the arrays in the declaration. No length information is necessary in the map clause, as is required with C/C++ pointers. \ffreeexample[4.0]{target_data}{1} \subsection{\kcode{target data} Region Enclosing Multiple \kcode{target} Regions} \label{subsec:target_data_multiregion} The following examples show how the \kcode{target data} construct maps variables to a device data environment of a \kcode{target} region. The \kcode{target data} construct creates a device data environment and encloses \kcode{target} regions, which have their own device data environments. The device data environment of the \kcode{target data} region is inherited by the device data environment of an enclosed \kcode{target} region. The \kcode{target data} construct is used to create variables that will persist throughout the \kcode{target data} region. In the following example the variables \ucode{v1} and \ucode{v2} are mapped at each \kcode{target} construct. Instead of mapping the variable \ucode{p} twice, once at each \kcode{target} construct, \ucode{p} is mapped once by the \kcode{target data} construct. \cexample[4.0]{target_data}{2} The Fortran code uses reference and specifies the extent of the \ucode{p}, \ucode{v1} and \ucode{v2} arrays. No length information is necessary in the \kcode{map} clause, as is required with C/C++ pointers. The arrays \ucode{v1} and \ucode{v2} are mapped at each \kcode{target} construct. Instead of mapping the array \ucode{p} twice, once at each target construct, \ucode{p} is mapped once by the \kcode{target data} construct. \ffreeexample[4.0]{target_data}{2} \index{target data construct@\kcode{target data} construct!map clause@\kcode{map} clause} \index{target construct@\kcode{target} construct!map clause@\kcode{map} clause} \index{target construct@\kcode{target} construct!implicit mapping} \index{map clause@\kcode{map} clause!tofrom map-type@\kcode{tofrom} map-type} In the following example, the array \ucode{Q} is mapped once at the enclosing \kcode{target data} region instead of at each \kcode{target} construct. In OpenMP 4.0, a scalar variable is implicitly mapped with the \kcode{tofrom} map-type. But since OpenMP 4.5, a scalar variable, such as the \ucode{tmp} variable, has to be explicitly mapped with the \kcode{tofrom} map-type at the first \kcode{target} construct in order to return its reduced value from the parallel loop construct to the host. The variable defaults to firstprivate at the second \kcode{target} construct. \cexample[4.0]{target_data}{3} \ffreeexample[4.0]{target_data}{3} \subsection{\kcode{target data} Construct with Orphaned Call} The following two examples show how the \kcode{target data} construct maps variables to a device data environment. The \kcode{target data} construct's device data environment encloses the \kcode{target} construct's device data environment in the function \ucode{vec_mult()}. \index{map clause@\kcode{map} clause!alloc map-type@\kcode{alloc} map-type} When the type of the variable appearing in an array section is pointer, the pointer variable and the storage location of the corresponding array section are mapped to the device data environment. The pointer variable is treated as if it had appeared in a \kcode{map} clause with a map-type of \kcode{alloc}. The array section's storage location is mapped according to the map-type in the \kcode{map} clause (the default map-type is \kcode{tofrom}). The \kcode{target} construct's device data environment inherits the storage locations of the array sections \ucode{v1[0:N]}, \ucode{v2[:n]}, and \ucode{p0[0:N]} from the enclosing \kcode{target data} construct's device data environment. Neither initialization nor assignment is performed for the array sections in the new device data environment. The pointer variables \ucode{p1}, \ucode{v3}, and \ucode{v4} are mapped into the \kcode{target} construct's device data environment with an implicit map-type of alloc and they are assigned the address of the storage location associated with their corresponding array sections. Note that the following pairs of array section storage locations are equivalent (\ucode{p0[:N]}, \ucode{p1[:N]}), (\ucode{v1[:N]},\ucode{v3[:N]}), and (\ucode{v2[:N]},\ucode{v4[:N]}). \cexample[4.0]{target_data}{4} The Fortran code maps the pointers and storage in an identical manner (same extent, but uses indices from 1 to \ucode{N}). The \kcode{target} construct's device data environment inherits the storage locations of the arrays \ucode{v1}, \ucode{v2} and \ucode{p0} from the enclosing \kcode{target data} constructs's device data environment. However, in Fortran the associated data of the pointer is known, and the shape is not required. The pointer variables \ucode{p1}, \ucode{v3}, and \ucode{v4} are mapped into the \kcode{target} construct's device data environment with an implicit map-type of \kcode{alloc} and they are assigned the address of the storage location associated with their corresponding array sections. Note that the following pair of array storage locations are equivalent (\ucode{p0},\ucode{p1}), (\ucode{v1},\ucode{v3}), and (\ucode{v2},\ucode{v4}). \ffreeexample[4.0]{target_data}{4} In the following example, the variables \ucode{p1}, \ucode{v3}, and \ucode{v4} are references to the pointer variables \ucode{p0}, \ucode{v1} and \ucode{v2} respectively. The \kcode{target} construct's device data environment inherits the pointer variables \ucode{p0}, \ucode{v1}, and \ucode{v2} from the enclosing \kcode{target data} construct's device data environment. Thus, \ucode{p1}, \ucode{v3}, and \ucode{v4} are already present in the device data environment. \cppexample[4.0]{target_data}{5} In the following example, the usual Fortran approach is used for dynamic memory. The \ucode{p0}, \ucode{v1}, and \ucode{v2} arrays are allocated in the main program and passed as references from one routine to another. In \ucode{vec_mult}, \ucode{p1}, \ucode{v3} and \ucode{v4} are references to the \ucode{p0}, \ucode{v1}, and \ucode{v2} arrays, respectively. The \kcode{target} construct's device data environment inherits the arrays \ucode{p0}, \ucode{v1}, and \ucode{v2} from the enclosing target data construct's device data environment. Thus, \ucode{p1}, \ucode{v3}, and \ucode{v4} are already present in the device data environment. \ffreeexample[4.0]{target_data}{5} \subsection{\kcode{target data} Construct with \kcode{if} Clause} \label{subsec:target_data_if} \index{target data construct@\kcode{target data} construct!if clause@\kcode{if} clause} \index{clauses!if@\kcode{if}} \index{if clause@\kcode{if} clause} The following two examples show how the \kcode{target data} construct maps variables to a device data environment. In the following example, the if clause on the \kcode{target data} construct indicates that if the variable \ucode{N} is smaller than a given threshold, then the \kcode{target data} construct will not create a device data environment. The \kcode{target} constructs enclosed in the \kcode{target data} region must also use an \kcode{if} clause on the same condition, otherwise the pointer variable \ucode{p} is implicitly mapped with a map-type of \kcode{tofrom}, but the storage location for the array section \ucode{p[0:N]} will not be mapped in the device data environments of the \kcode{target} constructs. \cexample[4.0]{target_data}{6} %\pagebreak The \kcode{if} clauses work the same way for the following Fortran code. The \kcode{target} constructs enclosed in the \kcode{target data} region should also use an \kcode{if} clause with the same condition, so that the \kcode{target data} region and the \kcode{target} region are either both created for the device, or are both ignored. \ffreeexample[4.0]{target_data}{6} %\pagebreak In the following example, when the \kcode{if} clause conditional expression on the \kcode{target} construct evaluates to \vcode{false}, the target region will execute on the host device. However, the \kcode{target data} construct created an enclosing device data environment that mapped \ucode{p[0:N]} to a device data environment on the default device. At the end of the \kcode{target data} region the array section \ucode{p[0:N]} will be assigned from the device data environment to the corresponding variable in the data environment of the task that encountered the \kcode{target data} construct, resulting in undefined values in \ucode{p[0:N]}. \cexample[4.0]{target_data}{7} %\pagebreak The \kcode{if} clauses work the same way for the following Fortran code. When the \kcode{if} clause conditional expression on the \kcode{target} construct evaluates to \vcode{false}, the \kcode{target} region will execute on the host device. However, the \kcode{target data} construct created an enclosing device data environment that mapped the \ucode{p} array (and \ucode{v1} and \ucode{v2}) to a device data environment on the default target device. At the end of the \kcode{target data} region the \ucode{p} array will be assigned from the device data environment to the corresponding variable in the data environment of the task that encountered the \kcode{target data} construct, resulting in undefined values in \ucode{p}. \ffreeexample[4.0]{target_data}{7}