[PATCH 07/13] OpenACC 2.6 deep copy: libgomp parts
Julian Brown
julian@codesourcery.com
Wed Dec 18 06:05:00 GMT 2019
This patch has been broken out of the "OpenACC 2.6 manual deep copy
support" patch, last posted here:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg02376.html
This part contains the libgomp runtime support for the GOMP_MAP_ATTACH and
GOMP_MAP_DETACH mapping kinds (etc.), as introduced by the front-end
patches following in this series.
Tested alongside other patches in this series with offloading to
NVPTX. OK?
Thanks,
Julian
ChangeLog
include/
* gomp-constants.h (GOMP_MAP_FLAG_SPECIAL_4, GOMP_MAP_DEEP_COPY):
Define.
(gomp_map_kind): Add GOMP_MAP_ATTACH, GOMP_MAP_DETACH,
GOMP_MAP_FORCE_DETACH.
libgomp/
* libgomp.h (struct target_var_desc): Add do_detach flag.
* oacc-init.c (acc_shutdown_1): Free aux block if present.
* oacc-mem.c (find_group_last): Add SIZES parameter. Support
struct components. Tidy up and add some new checks.
(goacc_enter_data_internal): Update call to find_group_last.
(goacc_exit_data_internal): Support detach operations and
GOMP_MAP_STRUCT.
(GOACC_enter_exit_data): Handle initial GOMP_MAP_STRUCT or
GOMP_MAP_FORCE_PRESENT in finalization detection code. Handle
attach/detach in enter/exit data detection code.
* target.c (gomp_map_vars_existing): Initialise do_detach field of
tgt_var_desc.
(gomp_map_vars_internal): Support attach.
(gomp_unmap_vars_internal): Support detach.
---
include/gomp-constants.h | 10 ++++
libgomp/libgomp.h | 2 +
libgomp/oacc-mem.c | 121 +++++++++++++++++++++++++++++++++------
libgomp/target.c | 51 ++++++++++++++++-
4 files changed, 166 insertions(+), 18 deletions(-)
diff --git a/include/gomp-constants.h b/include/gomp-constants.h
index 9e356cdfeec..e8bd52e81bd 100644
--- a/include/gomp-constants.h
+++ b/include/gomp-constants.h
@@ -40,8 +40,11 @@
#define GOMP_MAP_FLAG_SPECIAL_0 (1 << 2)
#define GOMP_MAP_FLAG_SPECIAL_1 (1 << 3)
#define GOMP_MAP_FLAG_SPECIAL_2 (1 << 4)
+#define GOMP_MAP_FLAG_SPECIAL_4 (1 << 6)
#define GOMP_MAP_FLAG_SPECIAL (GOMP_MAP_FLAG_SPECIAL_1 \
| GOMP_MAP_FLAG_SPECIAL_0)
+#define GOMP_MAP_DEEP_COPY (GOMP_MAP_FLAG_SPECIAL_4 \
+ | GOMP_MAP_FLAG_SPECIAL_2)
/* Flag to force a specific behavior (or else, trigger a run-time error). */
#define GOMP_MAP_FLAG_FORCE (1 << 7)
@@ -127,6 +130,13 @@ enum gomp_map_kind
/* Decrement usage count and deallocate if zero. */
GOMP_MAP_RELEASE = (GOMP_MAP_FLAG_SPECIAL_2
| GOMP_MAP_DELETE),
+ /* In OpenACC, attach a pointer to a mapped struct field. */
+ GOMP_MAP_ATTACH = (GOMP_MAP_DEEP_COPY | 0),
+ /* In OpenACC, detach a pointer to a mapped struct field. */
+ GOMP_MAP_DETACH = (GOMP_MAP_DEEP_COPY | 1),
+ /* In OpenACC, detach a pointer to a mapped struct field. */
+ GOMP_MAP_FORCE_DETACH = (GOMP_MAP_DEEP_COPY
+ | GOMP_MAP_FLAG_FORCE | 1),
/* Internal to GCC, not used in libgomp. */
/* Do not map, but pointer assign a pointer instead. */
diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h
index 2017991b59c..6141cc117bc 100644
--- a/libgomp/libgomp.h
+++ b/libgomp/libgomp.h
@@ -948,6 +948,8 @@ struct target_var_desc {
bool copy_from;
/* True if data always should be copied from device to host at the end. */
bool always_copy_from;
+ /* True if variable should be detached at end of region. */
+ bool do_detach;
/* Relative offset against key host_start. */
uintptr_t offset;
/* Actual length. */
diff --git a/libgomp/oacc-mem.c b/libgomp/oacc-mem.c
index 08507791399..ce9f2759dfa 100644
--- a/libgomp/oacc-mem.c
+++ b/libgomp/oacc-mem.c
@@ -956,33 +956,48 @@ acc_detach_finalize_async (void **hostaddr, int async)
mappings. */
static int
-find_group_last (int pos, size_t mapnum, unsigned short *kinds)
+find_group_last (int pos, size_t mapnum, size_t *sizes, unsigned short *kinds)
{
unsigned char kind0 = kinds[pos] & 0xff;
- int first_pos = pos, last_pos = pos;
+ int first_pos = pos;
- if (kind0 == GOMP_MAP_TO_PSET)
+ switch (kind0)
{
+ case GOMP_MAP_TO_PSET:
while (pos + 1 < mapnum && (kinds[pos + 1] & 0xff) == GOMP_MAP_POINTER)
- last_pos = ++pos;
+ pos++;
/* We expect at least one GOMP_MAP_POINTER after a GOMP_MAP_TO_PSET. */
- assert (last_pos > first_pos);
- }
- else
- {
+ assert (pos > first_pos);
+ break;
+
+ case GOMP_MAP_STRUCT:
+ pos += sizes[pos];
+ break;
+
+ case GOMP_MAP_POINTER:
+ case GOMP_MAP_ALWAYS_POINTER:
+ /* These mappings are only expected after some other mapping. If we
+ see one by itself, something has gone wrong. */
+ gomp_fatal ("unexpected mapping");
+ break;
+
+ default:
/* GOMP_MAP_ALWAYS_POINTER can only appear directly after some other
mapping. */
- if (pos + 1 < mapnum
- && (kinds[pos + 1] & 0xff) == GOMP_MAP_ALWAYS_POINTER)
- return pos + 1;
+ if (pos + 1 < mapnum)
+ {
+ unsigned char kind1 = kinds[pos + 1] & 0xff;
+ if (kind1 == GOMP_MAP_ALWAYS_POINTER)
+ return pos + 1;
+ }
- /* We can have one or several GOMP_MAP_POINTER mappings after a to/from
+ /* We can have zero or more GOMP_MAP_POINTER mappings after a to/from
(etc.) mapping. */
while (pos + 1 < mapnum && (kinds[pos + 1] & 0xff) == GOMP_MAP_POINTER)
- last_pos = ++pos;
+ pos++;
}
- return last_pos;
+ return pos;
}
/* Map variables for OpenACC "enter data". We can't just call
@@ -996,7 +1011,7 @@ goacc_enter_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
{
for (size_t i = 0; i < mapnum; i++)
{
- int group_last = find_group_last (i, mapnum, kinds);
+ int group_last = find_group_last (i, mapnum, sizes, kinds);
gomp_map_vars_async (acc_dev, aq,
(group_last - i) + 1,
@@ -1018,6 +1033,33 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
{
gomp_mutex_lock (&acc_dev->lock);
+ /* Handle "detach" before copyback/deletion of mapped data. */
+ for (size_t i = 0; i < mapnum; ++i)
+ {
+ unsigned char kind = kinds[i] & 0xff;
+ switch (kind)
+ {
+ case GOMP_MAP_DETACH:
+ case GOMP_MAP_FORCE_DETACH:
+ {
+ struct splay_tree_key_s cur_node;
+ uintptr_t hostaddr = (uintptr_t) hostaddrs[i];
+ cur_node.host_start = hostaddr;
+ cur_node.host_end = cur_node.host_start + sizeof (void *);
+ splay_tree_key n
+ = splay_tree_lookup (&acc_dev->mem_map, &cur_node);
+
+ if (n == NULL)
+ gomp_fatal ("struct not mapped for detach operation");
+
+ gomp_detach_pointer (acc_dev, aq, n, hostaddr, finalize, NULL);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+
for (size_t i = 0; i < mapnum; ++i)
{
unsigned char kind = kinds[i] & 0xff;
@@ -1035,6 +1077,8 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
case GOMP_MAP_POINTER:
case GOMP_MAP_DELETE:
case GOMP_MAP_RELEASE:
+ case GOMP_MAP_DETACH:
+ case GOMP_MAP_FORCE_DETACH:
{
struct splay_tree_key_s cur_node;
cur_node.host_start = (uintptr_t) hostaddrs[i];
@@ -1075,6 +1119,39 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
gomp_remove_var_async (acc_dev, n, aq);
}
break;
+
+ case GOMP_MAP_STRUCT:
+ {
+ int elems = sizes[i];
+ for (int j = 1; j <= elems; j++)
+ {
+ struct splay_tree_key_s k;
+ k.host_start = (uintptr_t) hostaddrs[i + j];
+ k.host_end = k.host_start + sizes[i + j];
+ splay_tree_key str;
+ str = splay_tree_lookup (&acc_dev->mem_map, &k);
+ if (str)
+ {
+ if (finalize)
+ {
+ str->refcount -= str->virtual_refcount;
+ str->virtual_refcount = 0;
+ }
+ if (str->virtual_refcount > 0)
+ {
+ str->refcount--;
+ str->virtual_refcount--;
+ }
+ else if (str->refcount > 0)
+ str->refcount--;
+ if (str->refcount == 0)
+ gomp_remove_var_async (acc_dev, str, aq);
+ }
+ }
+ i += elems;
+ }
+ break;
+
default:
gomp_fatal (">>>> goacc_exit_data_internal UNHANDLED kind 0x%.2x",
kind);
@@ -1107,8 +1184,13 @@ GOACC_enter_exit_data (int flags_m, size_t mapnum, void **hostaddrs,
if (mapnum > 0)
{
unsigned char kind = kinds[0] & 0xff;
+
+ if (kind == GOMP_MAP_STRUCT || kind == GOMP_MAP_FORCE_PRESENT)
+ kind = kinds[1] & 0xff;
+
if (kind == GOMP_MAP_DELETE
- || kind == GOMP_MAP_FORCE_FROM)
+ || kind == GOMP_MAP_FORCE_FROM
+ || kind == GOMP_MAP_FORCE_DETACH)
finalize = true;
}
@@ -1117,11 +1199,14 @@ GOACC_enter_exit_data (int flags_m, size_t mapnum, void **hostaddrs,
{
unsigned char kind = kinds[i] & 0xff;
- if (kind == GOMP_MAP_POINTER || kind == GOMP_MAP_TO_PSET)
+ if (kind == GOMP_MAP_POINTER
+ || kind == GOMP_MAP_TO_PSET
+ || kind == GOMP_MAP_STRUCT)
continue;
if (kind == GOMP_MAP_FORCE_ALLOC
|| kind == GOMP_MAP_FORCE_PRESENT
+ || kind == GOMP_MAP_ATTACH
|| kind == GOMP_MAP_FORCE_TO
|| kind == GOMP_MAP_TO
|| kind == GOMP_MAP_ALLOC)
@@ -1132,6 +1217,8 @@ GOACC_enter_exit_data (int flags_m, size_t mapnum, void **hostaddrs,
if (kind == GOMP_MAP_RELEASE
|| kind == GOMP_MAP_DELETE
+ || kind == GOMP_MAP_DETACH
+ || kind == GOMP_MAP_FORCE_DETACH
|| kind == GOMP_MAP_FROM
|| kind == GOMP_MAP_FORCE_FROM)
break;
diff --git a/libgomp/target.c b/libgomp/target.c
index 1f429900113..6fa94dec6ce 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -540,6 +540,7 @@ gomp_map_vars_existing (struct gomp_device_descr *devicep,
tgt_var->key = oldn;
tgt_var->copy_from = GOMP_MAP_COPY_FROM_P (kind);
tgt_var->always_copy_from = GOMP_MAP_ALWAYS_FROM_P (kind);
+ tgt_var->do_detach = kind == GOMP_MAP_ATTACH;
tgt_var->offset = newn->host_start - oldn->host_start;
tgt_var->length = newn->host_end - newn->host_start;
@@ -978,8 +979,15 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
has_firstprivate = true;
continue;
}
+ else if ((kind & typemask) == GOMP_MAP_ATTACH)
+ {
+ tgt->list[i].key = NULL;
+ has_firstprivate = true;
+ continue;
+ }
cur_node.host_start = (uintptr_t) hostaddrs[i];
- if (!GOMP_MAP_POINTER_P (kind & typemask))
+ if (!GOMP_MAP_POINTER_P (kind & typemask)
+ && (kind & typemask) != GOMP_MAP_ATTACH)
cur_node.host_end = cur_node.host_start + sizes[i];
else
cur_node.host_end = cur_node.host_start + sizeof (void *);
@@ -1203,6 +1211,32 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
cur_node.tgt_offset = n->tgt->tgt_start + n->tgt_offset
+ cur_node.host_start - n->host_start;
continue;
+ case GOMP_MAP_ATTACH:
+ {
+ cur_node.host_start = (uintptr_t) hostaddrs[i];
+ cur_node.host_end = cur_node.host_start + sizeof (void *);
+ splay_tree_key n = splay_tree_lookup (mem_map, &cur_node);
+ if (n != NULL)
+ {
+ tgt->list[i].key = n;
+ tgt->list[i].offset = cur_node.host_start - n->host_start;
+ tgt->list[i].length = n->host_end - n->host_start;
+ tgt->list[i].copy_from = false;
+ tgt->list[i].always_copy_from = false;
+ tgt->list[i].do_detach
+ = (pragma_kind != GOMP_MAP_VARS_OPENACC_ENTER_DATA);
+ n->refcount++;
+ }
+ else
+ {
+ gomp_mutex_unlock (&devicep->lock);
+ gomp_fatal ("outer struct not mapped for attach");
+ }
+ gomp_attach_pointer (devicep, aq, mem_map, n,
+ (uintptr_t) hostaddrs[i], sizes[i],
+ cbufp);
+ continue;
+ }
default:
break;
}
@@ -1247,10 +1281,12 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
tgt->list[i].copy_from = GOMP_MAP_COPY_FROM_P (kind & typemask);
tgt->list[i].always_copy_from
= GOMP_MAP_ALWAYS_FROM_P (kind & typemask);
+ tgt->list[i].do_detach = false;
tgt->list[i].offset = 0;
tgt->list[i].length = k->host_end - k->host_start;
k->refcount = 1;
k->virtual_refcount = 0;
+ k->aux = NULL;
tgt->refcount++;
array->left = NULL;
array->right = NULL;
@@ -1301,6 +1337,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
tgt->list[j].key = k;
tgt->list[j].copy_from = false;
tgt->list[j].always_copy_from = false;
+ tgt->list[j].do_detach = false;
if (k->refcount != REFCOUNT_INFINITY)
k->refcount++;
gomp_map_pointer (tgt, aq,
@@ -1534,6 +1571,18 @@ gomp_unmap_vars_internal (struct target_mem_desc *tgt, bool do_copyfrom,
}
size_t i;
+
+ /* We must perform detachments before any copies back to the host. */
+ for (i = 0; i < tgt->list_count; i++)
+ {
+ splay_tree_key k = tgt->list[i].key;
+
+ if (k != NULL && tgt->list[i].do_detach)
+ gomp_detach_pointer (devicep, aq, k, tgt->list[i].key->host_start
+ + tgt->list[i].offset,
+ k->refcount == 1, NULL);
+ }
+
for (i = 0; i < tgt->list_count; i++)
{
splay_tree_key k = tgt->list[i].key;
--
2.23.0
More information about the Gcc-patches
mailing list