OpenMP Offloading Validation & Verification Suite; Official repository. We have migrated from bitbucket!! For documentation, results, publication and presentations, please check out our website ->
INTEGER, POINTER :: first_scalar_device_addr
...
!$omp target map(from: first_scalar_device_addr, first_arr_device_addr) map(to: x, arr)
first_scalar_device_addr => x
...
!$omp end target
There are multiple problems with this:
"The association status of a list item that is a pointer must not be undefined unless it is a structure component and it results from a predefined default mapper." (TR11 [160:15–16], "5.8.3 map Clause" under "Restrictions to the map clause")
While only added in TR11, it is a bug fix to the specification and not a new feature. The background for that change is (TR11 wording but feature is old):
If a list item in a map clause is an associated pointer that is not attach-ineligible and the pointer is not the base pointer of another list item in a map clause on the same construct, then it is treated as if its pointer target is implicitly mapped in the same clause.
The problem is that a compiler cannot distinguish an undefined pointer from an associated pointer.
Solution: you need to nullify() / null() the pointer before mapping.
The following feature – here, the second bullet applies (at least after nullifying):
If the association status of a list item with the POINTER attribute that appears in a map clause on the construct is associated upon entry to the target region, the list item must be associated with the same pointer target upon exit from the region.
If the association status of a list item with the POINTER attribute that appears in a map clause on the construct is disassociated upon entry to the target region, the list item must be disassociated upon exit from the region.
(OpenMP 5.2 [287:29-31, 288:1-3], "Restrictions to the target construct" in "13.8 target Construct")
While only in OpenMP 5.2, the issue is generic — and also the main reason that the testcase has problems. Namely, the following applies:
At least for arrays, all Fortran implementations use an array descriptor, which is a struct containing the array bounds and usually also the data size, some attributes, the type, — and a pointer to the bare data.
For "map(tofrom: array)", implementations usually copy-in (or firstprivatize) the array descriptor and only the actual data is copied from/to. This implies:
Changing an array descriptor is bad as then there is a host/device mismatch of the data pointed to for copying back the actual data — In cases of pointers, copying back the pointer itself (the array descriptor) would be fine but Fortran rules require (see quote above) that "map(ptr)" implies mapping both the pointer and the pointer target.
In order to avoid copying back the array descriptor (performance) and because of the bullet before (technical issue), the spec does not want to demand the copying back — and implementations also do not do so
There is also the consistency problem with when host and device share memory and the 'map' is a self map: If the pointer is updated on the device , it (the array descriptor) is also updated on the host – but if 'map' actually copies the data/the array descriptor, the descriptor is not updated on the host after exiting from the target region.
For the reasons mentioned above, the restriction was added in 5.2 and in TR11 — while the restrictions are new, the issue itself also applied to 5.1 and earlier.
What means "has_device_addr"
Namely: Does it apply to the array descriptor / pointer itself — or to the address it points to. It was clarified in TR11 that it applies to the address it points to. Upon entering a target region, those are taken from the host (by copying in/firstprivatizing the array descriptor; the pointer attribute inside of it is then the device one):
"For a list item in a has_device_addr clause, the CONTIGUOUS attribute, storage location, storage size, array bounds, character length, association status and allocation status (as applicable) are the same inside the construct on which the clause appears as for the original list item. The result of inquiring about other list item properties inside the structured block is implementation defined. For a list item that is an array section, the array bounds and result when invoking CLOC inside the structured block is the same as if the base expression had been specified in the clause instead." (TR11 [124:28-33], "5.4.9 has_device_addr Clause").
Fortran's "associated" intrinsic
For completeness, I want to point out that the Fortran "associated" intrinsic for arrays not only check the pointer address but also that the array bounds match. That's not a problem here, but I want to point out that that's the case.
→ https://github.com/SOLLVE/sollve_vv/blob/master/tests/5.1/target/test_target_has_device_addr.F90 → Was added in Pull Request #717
The code does:
There are multiple problems with this:
While only added in TR11, it is a bug fix to the specification and not a new feature. The background for that change is (TR11 wording but feature is old):
The problem is that a compiler cannot distinguish an undefined pointer from an associated pointer.
Solution: you need to nullify() / null() the pointer before mapping.
(OpenMP 5.2 [287:29-31, 288:1-3], "Restrictions to the target construct" in "13.8 target Construct")
While only in OpenMP 5.2, the issue is generic — and also the main reason that the testcase has problems. Namely, the following applies:
For the reasons mentioned above, the restriction was added in 5.2 and in TR11 — while the restrictions are new, the issue itself also applied to 5.1 and earlier.
Namely: Does it apply to the array descriptor / pointer itself — or to the address it points to. It was clarified in TR11 that it applies to the address it points to. Upon entering a target region, those are taken from the host (by copying in/firstprivatizing the array descriptor; the pointer attribute inside of it is then the device one):
For completeness, I want to point out that the Fortran "associated" intrinsic for arrays not only check the pointer address but also that the array bounds match. That's not a problem here, but I want to point out that that's the case.
@seyonglee @fel-cab @spophale