Commit 8e7e71ff by Julian Brown Committed by Julian Brown

OpenACC 2.6 deep copy: libgomp parts

	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.

From-SVN: r279625
parent 5d5be7bf
2019-12-19 Julian Brown <julian@codesourcery.com> 2019-12-19 Julian Brown <julian@codesourcery.com>
* 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.
2019-12-19 Julian Brown <julian@codesourcery.com>
Maciej W. Rozycki <macro@codesourcery.com> Maciej W. Rozycki <macro@codesourcery.com>
Tobias Burnus <tobias@codesourcery.com> Tobias Burnus <tobias@codesourcery.com>
Thomas Schwinge <thomas@codesourcery.com> Thomas Schwinge <thomas@codesourcery.com>
......
...@@ -40,8 +40,11 @@ ...@@ -40,8 +40,11 @@
#define GOMP_MAP_FLAG_SPECIAL_0 (1 << 2) #define GOMP_MAP_FLAG_SPECIAL_0 (1 << 2)
#define GOMP_MAP_FLAG_SPECIAL_1 (1 << 3) #define GOMP_MAP_FLAG_SPECIAL_1 (1 << 3)
#define GOMP_MAP_FLAG_SPECIAL_2 (1 << 4) #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 \ #define GOMP_MAP_FLAG_SPECIAL (GOMP_MAP_FLAG_SPECIAL_1 \
| GOMP_MAP_FLAG_SPECIAL_0) | 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). */ /* Flag to force a specific behavior (or else, trigger a run-time error). */
#define GOMP_MAP_FLAG_FORCE (1 << 7) #define GOMP_MAP_FLAG_FORCE (1 << 7)
...@@ -129,6 +132,13 @@ enum gomp_map_kind ...@@ -129,6 +132,13 @@ enum gomp_map_kind
/* Decrement usage count and deallocate if zero. */ /* Decrement usage count and deallocate if zero. */
GOMP_MAP_RELEASE = (GOMP_MAP_FLAG_SPECIAL_2 GOMP_MAP_RELEASE = (GOMP_MAP_FLAG_SPECIAL_2
| GOMP_MAP_DELETE), | 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. */ /* Internal to GCC, not used in libgomp. */
/* Do not map, but pointer assign a pointer instead. */ /* Do not map, but pointer assign a pointer instead. */
......
2019-12-19 Julian Brown <julian@codesourcery.com> 2019-12-19 Julian Brown <julian@codesourcery.com>
* 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.
2019-12-19 Julian Brown <julian@codesourcery.com>
Thomas Schwinge <thomas@codesourcery.com> Thomas Schwinge <thomas@codesourcery.com>
* libgomp.h (struct splay_tree_aux): Add attach_count field. * libgomp.h (struct splay_tree_aux): Add attach_count field.
......
...@@ -948,6 +948,8 @@ struct target_var_desc { ...@@ -948,6 +948,8 @@ struct target_var_desc {
bool copy_from; bool copy_from;
/* True if data always should be copied from device to host at the end. */ /* True if data always should be copied from device to host at the end. */
bool always_copy_from; bool always_copy_from;
/* True if variable should be detached at end of region. */
bool do_detach;
/* Relative offset against key host_start. */ /* Relative offset against key host_start. */
uintptr_t offset; uintptr_t offset;
/* Actual length. */ /* Actual length. */
......
...@@ -957,33 +957,48 @@ acc_detach_finalize_async (void **hostaddr, int async) ...@@ -957,33 +957,48 @@ acc_detach_finalize_async (void **hostaddr, int async)
mappings. */ mappings. */
static int 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; 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) 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. */ /* We expect at least one GOMP_MAP_POINTER after a GOMP_MAP_TO_PSET. */
assert (last_pos > first_pos); assert (pos > first_pos);
} break;
else
{ 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 /* GOMP_MAP_ALWAYS_POINTER can only appear directly after some other
mapping. */ mapping. */
if (pos + 1 < mapnum if (pos + 1 < mapnum)
&& (kinds[pos + 1] & 0xff) == GOMP_MAP_ALWAYS_POINTER) {
return pos + 1; 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. */ (etc.) mapping. */
while (pos + 1 < mapnum && (kinds[pos + 1] & 0xff) == GOMP_MAP_POINTER) 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 /* Map variables for OpenACC "enter data". We can't just call
...@@ -997,7 +1012,7 @@ goacc_enter_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum, ...@@ -997,7 +1012,7 @@ goacc_enter_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
{ {
for (size_t i = 0; i < mapnum; i++) 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, gomp_map_vars_async (acc_dev, aq,
(group_last - i) + 1, (group_last - i) + 1,
...@@ -1018,6 +1033,37 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum, ...@@ -1018,6 +1033,37 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
{ {
gomp_mutex_lock (&acc_dev->lock); 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;
bool finalize = false;
switch (kind)
{
case GOMP_MAP_FORCE_DETACH:
finalize = true;
/* Fallthrough. */
case GOMP_MAP_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) for (size_t i = 0; i < mapnum; ++i)
{ {
unsigned char kind = kinds[i] & 0xff; unsigned char kind = kinds[i] & 0xff;
...@@ -1025,7 +1071,8 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum, ...@@ -1025,7 +1071,8 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
bool finalize = false; bool finalize = false;
if (kind == GOMP_MAP_FORCE_FROM if (kind == GOMP_MAP_FORCE_FROM
|| kind == GOMP_MAP_DELETE) || kind == GOMP_MAP_DELETE
|| kind == GOMP_MAP_FORCE_DETACH)
finalize = true; finalize = true;
switch (kind) switch (kind)
...@@ -1040,10 +1087,14 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum, ...@@ -1040,10 +1087,14 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
case GOMP_MAP_POINTER: case GOMP_MAP_POINTER:
case GOMP_MAP_DELETE: case GOMP_MAP_DELETE:
case GOMP_MAP_RELEASE: case GOMP_MAP_RELEASE:
case GOMP_MAP_DETACH:
case GOMP_MAP_FORCE_DETACH:
{ {
struct splay_tree_key_s cur_node; struct splay_tree_key_s cur_node;
size_t size; size_t size;
if (kind == GOMP_MAP_POINTER) if (kind == GOMP_MAP_POINTER
|| kind == GOMP_MAP_DETACH
|| kind == GOMP_MAP_FORCE_DETACH)
size = sizeof (void *); size = sizeof (void *);
else else
size = sizes[i]; size = sizes[i];
...@@ -1083,6 +1134,42 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum, ...@@ -1083,6 +1134,42 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum,
gomp_remove_var_async (acc_dev, n, aq); gomp_remove_var_async (acc_dev, n, aq);
} }
break; 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)
{
if (str->refcount != REFCOUNT_INFINITY)
str->refcount -= str->virtual_refcount;
str->virtual_refcount = 0;
}
if (str->virtual_refcount > 0)
{
if (str->refcount != REFCOUNT_INFINITY)
str->refcount--;
str->virtual_refcount--;
}
else if (str->refcount > 0
&& str->refcount != REFCOUNT_INFINITY)
str->refcount--;
if (str->refcount == 0)
gomp_remove_var_async (acc_dev, str, aq);
}
}
i += elems;
}
break;
default: default:
gomp_fatal (">>>> goacc_exit_data_internal UNHANDLED kind 0x%.2x", gomp_fatal (">>>> goacc_exit_data_internal UNHANDLED kind 0x%.2x",
kind); kind);
...@@ -1114,11 +1201,14 @@ GOACC_enter_exit_data (int flags_m, size_t mapnum, void **hostaddrs, ...@@ -1114,11 +1201,14 @@ GOACC_enter_exit_data (int flags_m, size_t mapnum, void **hostaddrs,
{ {
unsigned char kind = kinds[i] & 0xff; 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; continue;
if (kind == GOMP_MAP_FORCE_ALLOC if (kind == GOMP_MAP_FORCE_ALLOC
|| kind == GOMP_MAP_FORCE_PRESENT || kind == GOMP_MAP_FORCE_PRESENT
|| kind == GOMP_MAP_ATTACH
|| kind == GOMP_MAP_FORCE_TO || kind == GOMP_MAP_FORCE_TO
|| kind == GOMP_MAP_TO || kind == GOMP_MAP_TO
|| kind == GOMP_MAP_ALLOC) || kind == GOMP_MAP_ALLOC)
...@@ -1129,6 +1219,8 @@ GOACC_enter_exit_data (int flags_m, size_t mapnum, void **hostaddrs, ...@@ -1129,6 +1219,8 @@ GOACC_enter_exit_data (int flags_m, size_t mapnum, void **hostaddrs,
if (kind == GOMP_MAP_RELEASE if (kind == GOMP_MAP_RELEASE
|| kind == GOMP_MAP_DELETE || kind == GOMP_MAP_DELETE
|| kind == GOMP_MAP_DETACH
|| kind == GOMP_MAP_FORCE_DETACH
|| kind == GOMP_MAP_FROM || kind == GOMP_MAP_FROM
|| kind == GOMP_MAP_FORCE_FROM) || kind == GOMP_MAP_FORCE_FROM)
break; break;
......
...@@ -360,6 +360,7 @@ gomp_map_vars_existing (struct gomp_device_descr *devicep, ...@@ -360,6 +360,7 @@ gomp_map_vars_existing (struct gomp_device_descr *devicep,
tgt_var->key = oldn; tgt_var->key = oldn;
tgt_var->copy_from = GOMP_MAP_COPY_FROM_P (kind); tgt_var->copy_from = GOMP_MAP_COPY_FROM_P (kind);
tgt_var->always_copy_from = GOMP_MAP_ALWAYS_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->offset = newn->host_start - oldn->host_start;
tgt_var->length = newn->host_end - newn->host_start; tgt_var->length = newn->host_end - newn->host_start;
...@@ -798,8 +799,15 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep, ...@@ -798,8 +799,15 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
has_firstprivate = true; has_firstprivate = true;
continue; 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]; 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]; cur_node.host_end = cur_node.host_start + sizes[i];
else else
cur_node.host_end = cur_node.host_start + sizeof (void *); cur_node.host_end = cur_node.host_start + sizeof (void *);
...@@ -1046,6 +1054,32 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep, ...@@ -1046,6 +1054,32 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
== GOMP_MAP_POINTER)) == GOMP_MAP_POINTER))
++i; ++i;
continue; 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: default:
break; break;
} }
...@@ -1090,10 +1124,12 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep, ...@@ -1090,10 +1124,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].copy_from = GOMP_MAP_COPY_FROM_P (kind & typemask);
tgt->list[i].always_copy_from tgt->list[i].always_copy_from
= GOMP_MAP_ALWAYS_FROM_P (kind & typemask); = GOMP_MAP_ALWAYS_FROM_P (kind & typemask);
tgt->list[i].do_detach = false;
tgt->list[i].offset = 0; tgt->list[i].offset = 0;
tgt->list[i].length = k->host_end - k->host_start; tgt->list[i].length = k->host_end - k->host_start;
k->refcount = 1; k->refcount = 1;
k->virtual_refcount = 0; k->virtual_refcount = 0;
k->aux = NULL;
tgt->refcount++; tgt->refcount++;
array->left = NULL; array->left = NULL;
array->right = NULL; array->right = NULL;
...@@ -1144,6 +1180,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep, ...@@ -1144,6 +1180,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep,
tgt->list[j].key = k; tgt->list[j].key = k;
tgt->list[j].copy_from = false; tgt->list[j].copy_from = false;
tgt->list[j].always_copy_from = false; tgt->list[j].always_copy_from = false;
tgt->list[j].do_detach = false;
if (k->refcount != REFCOUNT_INFINITY) if (k->refcount != REFCOUNT_INFINITY)
k->refcount++; k->refcount++;
gomp_map_pointer (tgt, aq, gomp_map_pointer (tgt, aq,
...@@ -1377,6 +1414,18 @@ gomp_unmap_vars_internal (struct target_mem_desc *tgt, bool do_copyfrom, ...@@ -1377,6 +1414,18 @@ gomp_unmap_vars_internal (struct target_mem_desc *tgt, bool do_copyfrom,
} }
size_t i; 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++) for (i = 0; i < tgt->list_count; i++)
{ {
splay_tree_key k = tgt->list[i].key; splay_tree_key k = tgt->list[i].key;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment