Fix up 'libgomp.c++/target-std__[...]-concurrent-usm.C' dynamic memory allocation

OpenMP/USM implies memory accessible from host as well as device, but doesn't
imply that allocation vs. deallocation may be done in the opposite context.
For most of the test cases, (by construction) we're not allocating memory
during device execution, so have nothing to clean up.  (..., but still document
these semantics.)  But for a few, we have to clean up:
'libgomp.c++/target-std__map-concurrent-usm.C',
'libgomp.c++/target-std__multimap-concurrent-usm.C',
'libgomp.c++/target-std__multiset-concurrent-usm.C',
'libgomp.c++/target-std__set-concurrent-usm.C'.

For 'libgomp.c++/target-std__multimap-concurrent-usm.C' (only), this issue
already got addressed in commit 90f2ab4b6e
"libgomp.c++/target-std__multimap-concurrent.C: Fix USM memory freeing".
However, instead of invoking the 'clear' function (which doesn't generally
guarantee to release dynamically allocated memory; for example, see PR123582
"C++ unordered associative container: dynamic memory management"), we properly
restore the respective object into pristine state.

	libgomp/
	* testsuite/libgomp.c++/target-std__array-concurrent-usm.C:
	'#define OMP_USM'.
	* testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__list-concurrent-usm.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__span-concurrent-usm.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__map-concurrent-usm.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__set-concurrent-usm.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__vector-concurrent-usm.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__deque-concurrent-usm.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__array-concurrent.C: Comment.
	* testsuite/libgomp.c++/target-std__bitset-concurrent.C: Likewise.
	* testsuite/libgomp.c++/target-std__deque-concurrent.C: Likewise.
	* testsuite/libgomp.c++/target-std__forward_list-concurrent.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__list-concurrent.C: Likewise.
	* testsuite/libgomp.c++/target-std__span-concurrent.C: Likewise.
	* testsuite/libgomp.c++/target-std__valarray-concurrent.C:
	Likewise.
	* testsuite/libgomp.c++/target-std__vector-concurrent.C: Likewise.
	* testsuite/libgomp.c++/target-std__map-concurrent.C [OMP_USM]:
	Fix up dynamic memory allocation.
	* testsuite/libgomp.c++/target-std__multimap-concurrent.C
	[OMP_USM]: Likewise.
	* testsuite/libgomp.c++/target-std__multiset-concurrent.C
	[OMP_USM]: Likewise.
	* testsuite/libgomp.c++/target-std__set-concurrent.C [OMP_USM]:
	Likewise.
This commit is contained in:
Thomas Schwinge
2025-05-30 11:37:46 +02:00
parent 3dc9eedd95
commit e9e76f7607
24 changed files with 83 additions and 22 deletions

View File

@@ -1,7 +1,7 @@
/* { dg-require-effective-target omp_usm } */
// { dg-additional-options "-Wno-deprecated-openmp" }
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__array-concurrent.C"

View File

@@ -53,6 +53,11 @@ int main (void)
#pragma omp target map (from: ok)
{
ok = validate (arr, data);
#ifdef OMP_USM
/* (By construction) we're not allocating memory during device
execution, so have nothing to clean up. */
#endif
#ifndef MEM_SHARED
arr.~array ();
#endif

View File

@@ -1,6 +1,6 @@
/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__bitset-concurrent.C"

View File

@@ -58,6 +58,10 @@ int main (void)
if (_set[i])
sum += i;
#ifdef OMP_USM
/* (By construction) we're not allocating memory during device
execution, so have nothing to clean up. */
#endif
#ifndef MEM_SHARED
#pragma omp target
_set.~bitset ();

View File

@@ -1,7 +1,7 @@
/* { dg-require-effective-target omp_usm } */
// { dg-additional-options "-Wno-deprecated-openmp" }
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__deque-concurrent.C"

View File

@@ -54,6 +54,11 @@ int main (void)
#pragma omp target map (from: ok)
{
ok = validate (_deque, data);
#ifdef OMP_USM
/* (By construction) we're not allocating memory during device
execution, so have nothing to clean up. */
#endif
#ifndef MEM_SHARED
_deque.~deque ();
#endif

View File

@@ -1,7 +1,7 @@
/* { dg-require-effective-target omp_usm } */
// { dg-additional-options "-Wno-deprecated-openmp" }
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__forward_list-concurrent.C"

View File

@@ -73,6 +73,11 @@ int main (void)
#pragma omp target map (from: ok)
{
ok = validate (list, data);
#ifdef OMP_USM
/* (By construction) we're not allocating memory during device
execution, so have nothing to clean up. */
#endif
#ifndef MEM_SHARED
list.~forward_list ();
#endif

View File

@@ -1,7 +1,7 @@
/* { dg-require-effective-target omp_usm } */
// { dg-additional-options "-Wno-deprecated-openmp" }
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__list-concurrent.C"

View File

@@ -73,6 +73,11 @@ int main (void)
#pragma omp target map (from: ok)
{
ok = validate (_list, data);
#ifdef OMP_USM
/* (By construction) we're not allocating memory during device
execution, so have nothing to clean up. */
#endif
#ifndef MEM_SHARED
_list.~list ();
#endif

View File

@@ -1,6 +1,6 @@
/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__map-concurrent.C"

View File

@@ -56,6 +56,14 @@ int main (void)
for (int i = 0; i < N; ++i)
sum += (long long) keys[i] * _map[keys[i]];
#ifdef OMP_USM
#pragma omp target
/* Restore the object into pristine state. In particular, deallocate
any memory allocated during device execution, which otherwise, back
on the host, we'd SIGSEGV on, when attempting to deallocate during
destruction of the object. */
__typeof__ (_map){}.swap (_map);
#endif
#ifndef MEM_SHARED
#pragma omp target
_map.~map ();

View File

@@ -1,6 +1,6 @@
/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__multimap-concurrent.C"

View File

@@ -54,17 +54,15 @@ int main (void)
for (auto it = range.first; it != range.second; ++it)
sum += (long long) it->first * it->second;
}
#ifdef MEM_SHARED
/* Even with USM, memory allocated on the device (with _map.insert)
must be freed on the device. */
if (omp_get_default_device () != omp_initial_device
&& omp_get_default_device () != omp_get_num_devices ())
{
#pragma omp target
_map.clear ();
}
#endif
#ifdef OMP_USM
#pragma omp target
/* Restore the object into pristine state. In particular, deallocate
any memory allocated during device execution, which otherwise, back
on the host, we'd SIGSEGV on, when attempting to deallocate during
destruction of the object. */
__typeof__ (_map){}.swap (_map);
#endif
#ifndef MEM_SHARED
#pragma omp target
_map.~multimap ();

View File

@@ -1,6 +1,6 @@
/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__multiset-concurrent.C"

View File

@@ -51,6 +51,14 @@ int main (void)
for (int i = 0; i < MAX; ++i)
sum += i * set.count (i);
#ifdef OMP_USM
#pragma omp target
/* Restore the object into pristine state. In particular, deallocate
any memory allocated during device execution, which otherwise, back
on the host, we'd SIGSEGV on, when attempting to deallocate during
destruction of the object. */
__typeof__ (set){}.swap (set);
#endif
#ifndef MEM_SHARED
#pragma omp target
set.~multiset ();

View File

@@ -1,6 +1,6 @@
/* { dg-require-effective-target omp_usm } */
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__set-concurrent.C"

View File

@@ -57,6 +57,14 @@ int main (void)
if (_set.find (i) != _set.end ())
sum += i;
#ifdef OMP_USM
#pragma omp target
/* Restore the object into pristine state. In particular, deallocate
any memory allocated during device execution, which otherwise, back
on the host, we'd SIGSEGV on, when attempting to deallocate during
destruction of the object. */
__typeof__ (_set){}.swap (_set);
#endif
#ifndef MEM_SHARED
#pragma omp target
_set.~set ();

View File

@@ -2,7 +2,7 @@
/* { dg-require-effective-target omp_usm } */
// { dg-additional-options "-Wno-deprecated-openmp" }
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__span-concurrent.C"

View File

@@ -53,6 +53,11 @@ int main (void)
#pragma omp target map (from: ok)
{
ok = validate (span, data);
#ifdef OMP_USM
/* (By construction) we're not allocating memory during device
execution, so have nothing to clean up. */
#endif
#ifndef MEM_SHARED
span.~span ();
#endif

View File

@@ -1,7 +1,7 @@
/* { dg-require-effective-target omp_usm } */
// { dg-additional-options "-Wno-deprecated-openmp" }
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__valarray-concurrent.C"

View File

@@ -56,6 +56,11 @@ int main (void)
#pragma omp target map (from: ok)
{
ok = validate (arr, data);
#ifdef OMP_USM
/* (By construction) we're not allocating memory during device
execution, so have nothing to clean up. */
#endif
#ifndef MEM_SHARED
arr.~valarray ();
#endif

View File

@@ -1,7 +1,7 @@
/* { dg-require-effective-target omp_usm } */
// { dg-additional-options "-Wno-deprecated-openmp" }
#pragma omp requires unified_shared_memory self_maps
#define OMP_USM
#define MEM_SHARED
#include "target-std__vector-concurrent.C"

View File

@@ -53,6 +53,11 @@ int main (void)
#pragma omp target map (from: ok)
{
ok = validate (vec, data);
#ifdef OMP_USM
/* (By construction) we're not allocating memory during device
execution, so have nothing to clean up. */
#endif
#ifndef MEM_SHARED
vec.~vector ();
#endif