aboutsummaryrefslogtreecommitdiff
path: root/libgomp/oacc-init.c
diff options
context:
space:
mode:
authorjules <jules@138bc75d-0d04-0410-961f-82ee72b054a4>2015-04-08 15:58:33 +0000
committerjules <jules@138bc75d-0d04-0410-961f-82ee72b054a4>2015-04-08 15:58:33 +0000
commit0a1fe572e7c1b7e1770bd68f116528657e2ce125 (patch)
tree60d71a75181c79b311aaa199f917cb19ed8c06f7 /libgomp/oacc-init.c
parent1ddffe86a11e6a8f80ea4535523439f1af6ae3bb (diff)
gcc/
* config/nvptx/mkoffload.c (process): Support variable mapping. libgomp/ * libgomp.h (target_mem_desc: Remove mem_map field. (acc_dispatch_t): Remove open_device_func, close_device_func, get_device_num_func, set_device_num_func, target_data members. Change create_thread_data_func argument to device number instead of generic pointer. * oacc-async.c (assert.h): Include. (acc_async_test, acc_async_test_all, acc_wait, acc_wait_async) (acc_wait_all, acc_wait_all_async): Use current host thread's active device, not base_dev. * oacc-cuda.c (acc_get_current_cuda_device) (acc_get_current_cuda_context, acc_get_cuda_stream) (acc_set_cuda_stream): Likewise. * oacc-host.c (host_dispatch): Don't set open_device_func, close_device_func, get_device_num_func or set_device_num_func. * oacc-init.c (base_dev, init_key): Remove. (cached_base_dev): New. (name_of_acc_device_t): New. (acc_init_1): Initialise default-numbered device, not zeroth. (acc_shutdown_1): Close all devices of a given type. (goacc_destroy_thread): Don't use base_dev. (lazy_open, lazy_init, lazy_init_and_open): Remove. (goacc_attach_host_thread_to_device): New. (acc_init): Reimplement with goacc_attach_host_thread_to_device. (acc_get_num_devices): Don't use base_dev. (acc_set_device_type): Reimplement. (acc_get_device_type): Don't use base_dev. (acc_get_device_num): Tweak logic. (acc_set_device_num): Likewise. (acc_on_device): Use acc_get_device_type. (goacc_runtime_initialize): Initialize cached_base_dev not base_dev. (goacc_lazy_initialize): Reimplement with acc_init and goacc_attach_host_thread_to_device. * oacc-int.h (goacc_thread): Add base_dev field. (base_dev): Remove extern declaration. (goacc_attach_host_thread_to_device): Add prototype. * oacc-mem.c (acc_malloc): Use current thread's device instead of base_dev. (acc_free): Likewise. (acc_memcpy_to_device): Likewise. (acc_memcpy_from_device): Likewise. * oacc-parallel.c (select_acc_device): Remove. Replace calls with goacc_lazy_initialize (throughout). (GOACC_parallel): Use tgt_offset to locate target functions. * target.c (gomp_map_vars): Don't set tgt->mem_map. (gomp_unmap_vars): Use devicep->mem_map pointer not tgt->mem_map. (gomp_load_plugin_for_device): Remove open_device, close_device, get_device_num, set_device_num openacc hook initialisation. Don't set openacc.target_data. * plugin/plugin-host.c (GOMP_OFFLOAD_openacc_open_device) (GOMP_OFFLOAD_openacc_close_device) (GOMP_OFFLOAD_openacc_get_device_num) (GOMP_OFFLOAD_openacc_set_device_num): Remove. (GOMP_OFFLOAD_openacc_create_thread_data): Change (unused) argument to int. * plugin/plugin-nvptx.c (ptx_inited): Remove. (instantiated_devices, ptx_dev_lock): New. (struct ptx_image_data): New. (ptx_devices, ptx_images, ptx_image_lock): New. (fini_streams_for_device): Reorder cuStreamDestroy call. (nvptx_get_num_devices): Remove forward declaration. (nvptx_init): Change return type to bool. (nvptx_fini): Remove. (nvptx_attach_host_thread_to_device): New. (nvptx_open_device): Return struct ptx_device* instead of void*. (nvptx_close_device): Change argument type to struct ptx_device*, return type to void. (nvptx_get_num_devices): Use instantiated_devices not ptx_inited. (kernel_target_data, kernel_host_table): Remove static globals. (GOMP_OFFLOAD_register_image, GOMP_OFFLOAD_get_table): Remove. (GOMP_OFFLOAD_init_device): Reimplement. (GOMP_OFFLOAD_fini_device): Likewise. (GOMP_OFFLOAD_load_image, GOMP_OFFLOAD_unload_image): New. (GOMP_OFFLOAD_alloc, GOMP_OFFLOAD_free, GOMP_OFFLOAD_dev2host) (GOMP_OFFLOAD_host2dev): Use ORD argument. (GOMP_OFFLOAD_openacc_open_device) (GOMP_OFFLOAD_openacc_close_device) (GOMP_OFFLOAD_openacc_set_device_num) (GOMP_OFFLOAD_openacc_get_device_num): Remove. (GOMP_OFFLOAD_openacc_create_thread_data): Change argument to int (device number). libgomp/testsuite/ * libgomp.oacc-c-c++-common/lib-9.c: Fix devnum check in test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@221922 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgomp/oacc-init.c')
-rw-r--r--libgomp/oacc-init.c424
1 files changed, 205 insertions, 219 deletions
diff --git a/libgomp/oacc-init.c b/libgomp/oacc-init.c
index 1e0243ede44..dc40fb6ffe1 100644
--- a/libgomp/oacc-init.c
+++ b/libgomp/oacc-init.c
@@ -37,14 +37,13 @@
static gomp_mutex_t acc_device_lock;
-/* The dispatch table for the current accelerator device. This is global, so
- you can only have one type of device open at any given time in a program.
- This is the "base" device in that several devices that use the same
- dispatch table may be active concurrently: this one (the "zeroth") is used
- for overall initialisation/shutdown, and other instances -- not necessarily
- including this one -- may be opened and closed once the base device has
- been initialized. */
-struct gomp_device_descr *base_dev;
+/* A cached version of the dispatcher for the global "current" accelerator type,
+ e.g. used as the default when creating new host threads. This is the
+ device-type equivalent of goacc_device_num (which specifies which device to
+ use out of potentially several of the same type). If there are several
+ devices of a given type, this points at the first one. */
+
+static struct gomp_device_descr *cached_base_dev = NULL;
#if defined HAVE_TLS || defined USE_EMUTLS
__thread struct goacc_thread *goacc_tls_data;
@@ -53,9 +52,6 @@ pthread_key_t goacc_tls_key;
#endif
static pthread_key_t goacc_cleanup_key;
-/* Current dispatcher, and how it was initialized */
-static acc_device_t init_key = _ACC_device_hwm;
-
static struct goacc_thread *goacc_threads;
static gomp_mutex_t goacc_thread_lock;
@@ -94,6 +90,21 @@ get_openacc_name (const char *name)
return name;
}
+static const char *
+name_of_acc_device_t (enum acc_device_t type)
+{
+ switch (type)
+ {
+ case acc_device_none: return "none";
+ case acc_device_default: return "default";
+ case acc_device_host: return "host";
+ case acc_device_host_nonshm: return "host_nonshm";
+ case acc_device_not_host: return "not_host";
+ case acc_device_nvidia: return "nvidia";
+ default: gomp_fatal ("unknown device type %u", (unsigned) type);
+ }
+}
+
static struct gomp_device_descr *
resolve_device (acc_device_t d)
{
@@ -159,22 +170,87 @@ resolve_device (acc_device_t d)
static struct gomp_device_descr *
acc_init_1 (acc_device_t d)
{
- struct gomp_device_descr *acc_dev;
+ struct gomp_device_descr *base_dev, *acc_dev;
+ int ndevs;
- acc_dev = resolve_device (d);
+ base_dev = resolve_device (d);
+
+ ndevs = base_dev->get_num_devices_func ();
+
+ if (!base_dev || ndevs <= 0 || goacc_device_num >= ndevs)
+ gomp_fatal ("device %s not supported", name_of_acc_device_t (d));
- if (!acc_dev || acc_dev->get_num_devices_func () <= 0)
- gomp_fatal ("device %u not supported", (unsigned)d);
+ acc_dev = &base_dev[goacc_device_num];
if (acc_dev->is_initialized)
gomp_fatal ("device already active");
- /* We need to remember what we were intialized as, to check shutdown etc. */
- init_key = d;
-
gomp_init_device (acc_dev);
- return acc_dev;
+ return base_dev;
+}
+
+static void
+acc_shutdown_1 (acc_device_t d)
+{
+ struct gomp_device_descr *base_dev;
+ struct goacc_thread *walk;
+ int ndevs, i;
+ bool devices_active = false;
+
+ /* Get the base device for this device type. */
+ base_dev = resolve_device (d);
+
+ if (!base_dev)
+ gomp_fatal ("device %s not supported", name_of_acc_device_t (d));
+
+ gomp_mutex_lock (&goacc_thread_lock);
+
+ /* Free target-specific TLS data and close all devices. */
+ for (walk = goacc_threads; walk != NULL; walk = walk->next)
+ {
+ if (walk->target_tls)
+ base_dev->openacc.destroy_thread_data_func (walk->target_tls);
+
+ walk->target_tls = NULL;
+
+ /* This would mean the user is shutting down OpenACC in the middle of an
+ "acc data" pragma. Likely not intentional. */
+ if (walk->mapped_data)
+ gomp_fatal ("shutdown in 'acc data' region");
+
+ /* Similarly, if this happens then user code has done something weird. */
+ if (walk->saved_bound_dev)
+ gomp_fatal ("shutdown during host fallback");
+
+ if (walk->dev)
+ {
+ gomp_mutex_lock (&walk->dev->lock);
+ gomp_free_memmap (&walk->dev->mem_map);
+ gomp_mutex_unlock (&walk->dev->lock);
+
+ walk->dev = NULL;
+ walk->base_dev = NULL;
+ }
+ }
+
+ gomp_mutex_unlock (&goacc_thread_lock);
+
+ ndevs = base_dev->get_num_devices_func ();
+
+ /* Close all the devices of this type that have been opened. */
+ for (i = 0; i < ndevs; i++)
+ {
+ struct gomp_device_descr *acc_dev = &base_dev[i];
+ if (acc_dev->is_initialized)
+ {
+ devices_active = true;
+ gomp_fini_device (acc_dev);
+ }
+ }
+
+ if (!devices_active)
+ gomp_fatal ("no device initialized");
}
static struct goacc_thread *
@@ -207,9 +283,11 @@ goacc_destroy_thread (void *data)
if (thr)
{
- if (base_dev && thr->target_tls)
+ struct gomp_device_descr *acc_dev = thr->dev;
+
+ if (acc_dev && thr->target_tls)
{
- base_dev->openacc.destroy_thread_data_func (thr->target_tls);
+ acc_dev->openacc.destroy_thread_data_func (thr->target_tls);
thr->target_tls = NULL;
}
@@ -236,53 +314,49 @@ goacc_destroy_thread (void *data)
gomp_mutex_unlock (&goacc_thread_lock);
}
-/* Open the ORD'th device of the currently-active type (base_dev must be
- initialised before calling). If ORD is < 0, open the default-numbered
- device (set by the ACC_DEVICE_NUM environment variable or a call to
- acc_set_device_num), or leave any currently-opened device as is. "Opening"
- consists of calling the device's open_device_func hook, and setting up
- thread-local data (maybe allocating, then initializing with information
- pertaining to the newly-opened or previously-opened device). */
+/* Use the ORD'th device instance for the current host thread (or -1 for the
+ current global default). The device (and the runtime) must be initialised
+ before calling this function. */
-static void
-lazy_open (int ord)
+void
+goacc_attach_host_thread_to_device (int ord)
{
struct goacc_thread *thr = goacc_thread ();
- struct gomp_device_descr *acc_dev;
-
- if (thr && thr->dev)
- {
- assert (ord < 0 || ord == thr->dev->target_id);
- return;
- }
-
- assert (base_dev);
-
+ struct gomp_device_descr *acc_dev = NULL, *base_dev = NULL;
+ int num_devices;
+
+ if (thr && thr->dev && (thr->dev->target_id == ord || ord < 0))
+ return;
+
if (ord < 0)
ord = goacc_device_num;
-
- /* The OpenACC 2.0 spec leaves the runtime's behaviour when an out-of-range
- device is requested as implementation-defined (4.2 ACC_DEVICE_NUM).
- We choose to raise an error in such a case. */
- if (ord >= base_dev->get_num_devices_func ())
- gomp_fatal ("device %u does not exist", ord);
-
+
+ /* Decide which type of device to use. If the current thread has a device
+ type already (e.g. set by acc_set_device_type), use that, else use the
+ global default. */
+ if (thr && thr->base_dev)
+ base_dev = thr->base_dev;
+ else
+ {
+ assert (cached_base_dev);
+ base_dev = cached_base_dev;
+ }
+
+ num_devices = base_dev->get_num_devices_func ();
+ if (num_devices <= 0 || ord >= num_devices)
+ gomp_fatal ("device %u out of range", ord);
+
if (!thr)
thr = goacc_new_thread ();
-
- acc_dev = thr->dev = &base_dev[ord];
-
- assert (acc_dev->target_id == ord);
-
+
+ thr->base_dev = base_dev;
+ thr->dev = acc_dev = &base_dev[ord];
thr->saved_bound_dev = NULL;
thr->mapped_data = NULL;
-
- if (!acc_dev->openacc.target_data)
- acc_dev->openacc.target_data = acc_dev->openacc.open_device_func (ord);
-
+
thr->target_tls
- = acc_dev->openacc.create_thread_data_func (acc_dev->openacc.target_data);
-
+ = acc_dev->openacc.create_thread_data_func (ord);
+
acc_dev->openacc.async_set_async_func (acc_async_sync);
}
@@ -292,74 +366,20 @@ lazy_open (int ord)
void
acc_init (acc_device_t d)
{
- if (!base_dev)
+ if (!cached_base_dev)
gomp_init_targets_once ();
gomp_mutex_lock (&acc_device_lock);
- base_dev = acc_init_1 (d);
-
- lazy_open (-1);
+ cached_base_dev = acc_init_1 (d);
gomp_mutex_unlock (&acc_device_lock);
+
+ goacc_attach_host_thread_to_device (-1);
}
ialias (acc_init)
-static void
-acc_shutdown_1 (acc_device_t d)
-{
- struct goacc_thread *walk;
-
- /* We don't check whether d matches the actual device found, because
- OpenACC 2.0 (3.2.12) says the parameters to the init and this
- call must match (for the shutdown call anyway, it's silent on
- others). */
-
- if (!base_dev)
- gomp_fatal ("no device initialized");
- if (d != init_key)
- gomp_fatal ("device %u(%u) is initialized",
- (unsigned) init_key, (unsigned) base_dev->type);
-
- gomp_mutex_lock (&goacc_thread_lock);
-
- /* Free target-specific TLS data and close all devices. */
- for (walk = goacc_threads; walk != NULL; walk = walk->next)
- {
- if (walk->target_tls)
- base_dev->openacc.destroy_thread_data_func (walk->target_tls);
-
- walk->target_tls = NULL;
-
- /* This would mean the user is shutting down OpenACC in the middle of an
- "acc data" pragma. Likely not intentional. */
- if (walk->mapped_data)
- gomp_fatal ("shutdown in 'acc data' region");
-
- if (walk->dev)
- {
- void *target_data = walk->dev->openacc.target_data;
- if (walk->dev->openacc.close_device_func (target_data) < 0)
- gomp_fatal ("failed to close device");
-
- walk->dev->openacc.target_data = target_data = NULL;
-
- gomp_mutex_lock (&walk->dev->lock);
- gomp_free_memmap (&walk->dev->mem_map);
- gomp_mutex_unlock (&walk->dev->lock);
-
- walk->dev = NULL;
- }
- }
-
- gomp_mutex_unlock (&goacc_thread_lock);
-
- gomp_fini_device (base_dev);
-
- base_dev = NULL;
-}
-
void
acc_shutdown (acc_device_t d)
{
@@ -372,59 +392,16 @@ acc_shutdown (acc_device_t d)
ialias (acc_shutdown)
-/* This function is called after plugins have been initialized. It deals with
- the "base" device, and is used to prepare the runtime for dealing with a
- number of such devices (as implemented by some particular plugin). If the
- argument device type D matches a previous call to the function, return the
- current base device, else shut the old device down and re-initialize with
- the new device type. */
-
-static struct gomp_device_descr *
-lazy_init (acc_device_t d)
-{
- if (base_dev)
- {
- /* Re-initializing the same device, do nothing. */
- if (d == init_key)
- return base_dev;
-
- acc_shutdown_1 (init_key);
- }
-
- assert (!base_dev);
-
- return acc_init_1 (d);
-}
-
-/* Ensure that plugins are loaded, initialize and open the (default-numbered)
- device. */
-
-static void
-lazy_init_and_open (acc_device_t d)
-{
- if (!base_dev)
- gomp_init_targets_once ();
-
- gomp_mutex_lock (&acc_device_lock);
-
- base_dev = lazy_init (d);
-
- lazy_open (-1);
-
- gomp_mutex_unlock (&acc_device_lock);
-}
-
int
acc_get_num_devices (acc_device_t d)
{
int n = 0;
- const struct gomp_device_descr *acc_dev;
+ struct gomp_device_descr *acc_dev;
if (d == acc_device_none)
return 0;
- if (!base_dev)
- gomp_init_targets_once ();
+ gomp_init_targets_once ();
acc_dev = resolve_device (d);
if (!acc_dev)
@@ -439,10 +416,39 @@ acc_get_num_devices (acc_device_t d)
ialias (acc_get_num_devices)
+/* Set the device type for the current thread only (using the current global
+ default device number), initialising that device if necessary. Also set the
+ default device type for new threads to D. */
+
void
acc_set_device_type (acc_device_t d)
{
- lazy_init_and_open (d);
+ struct gomp_device_descr *base_dev, *acc_dev;
+ struct goacc_thread *thr = goacc_thread ();
+
+ gomp_mutex_lock (&acc_device_lock);
+
+ if (!cached_base_dev)
+ gomp_init_targets_once ();
+
+ cached_base_dev = base_dev = resolve_device (d);
+ acc_dev = &base_dev[goacc_device_num];
+
+ if (!acc_dev->is_initialized)
+ gomp_init_device (acc_dev);
+
+ gomp_mutex_unlock (&acc_device_lock);
+
+ /* We're changing device type: invalidate the current thread's dev and
+ base_dev pointers. */
+ if (thr && thr->base_dev != base_dev)
+ {
+ thr->base_dev = thr->dev = NULL;
+ if (thr->mapped_data)
+ gomp_fatal ("acc_set_device_type in 'acc data' region");
+ }
+
+ goacc_attach_host_thread_to_device (-1);
}
ialias (acc_set_device_type)
@@ -451,10 +457,11 @@ acc_device_t
acc_get_device_type (void)
{
acc_device_t res = acc_device_none;
- const struct gomp_device_descr *dev;
+ struct gomp_device_descr *dev;
+ struct goacc_thread *thr = goacc_thread ();
- if (base_dev)
- res = acc_device_type (base_dev->type);
+ if (thr && thr->base_dev)
+ res = acc_device_type (thr->base_dev->type);
else
{
gomp_init_targets_once ();
@@ -475,78 +482,65 @@ int
acc_get_device_num (acc_device_t d)
{
const struct gomp_device_descr *dev;
- int num;
+ struct goacc_thread *thr = goacc_thread ();
if (d >= _ACC_device_hwm)
gomp_fatal ("device %u out of range", (unsigned)d);
- if (!base_dev)
+ if (!cached_base_dev)
gomp_init_targets_once ();
dev = resolve_device (d);
if (!dev)
- gomp_fatal ("no devices of type %u", d);
+ gomp_fatal ("device %s not supported", name_of_acc_device_t (d));
- /* We might not have called lazy_open for this host thread yet, in which case
- the get_device_num_func hook will return -1. */
- num = dev->openacc.get_device_num_func ();
- if (num < 0)
- num = goacc_device_num;
+ if (thr && thr->base_dev == dev && thr->dev)
+ return thr->dev->target_id;
- return num;
+ return goacc_device_num;
}
ialias (acc_get_device_num)
void
-acc_set_device_num (int n, acc_device_t d)
+acc_set_device_num (int ord, acc_device_t d)
{
- const struct gomp_device_descr *dev;
+ struct gomp_device_descr *base_dev, *acc_dev;
int num_devices;
- if (!base_dev)
+ if (!cached_base_dev)
gomp_init_targets_once ();
- if ((int) d == 0)
- {
- int i;
-
- /* A device setting of zero sets all device types on the system to use
- the Nth instance of that device type. Only attempt it for initialized
- devices though. */
- for (i = acc_device_not_host + 1; i < _ACC_device_hwm; i++)
- {
- dev = resolve_device (d);
- if (dev && dev->is_initialized)
- dev->openacc.set_device_num_func (n);
- }
+ if (ord < 0)
+ ord = goacc_device_num;
- /* ...and for future calls to acc_init/acc_set_device_type, etc. */
- goacc_device_num = n;
- }
+ if ((int) d == 0)
+ /* Set whatever device is being used by the current host thread to use
+ device instance ORD. It's unclear if this is supposed to affect other
+ host threads too (OpenACC 2.0 (3.2.4) acc_set_device_num). */
+ goacc_attach_host_thread_to_device (ord);
else
{
- struct goacc_thread *thr = goacc_thread ();
-
gomp_mutex_lock (&acc_device_lock);
- base_dev = lazy_init (d);
+ cached_base_dev = base_dev = resolve_device (d);
num_devices = base_dev->get_num_devices_func ();
- if (n >= num_devices)
- gomp_fatal ("device %u out of range", n);
+ if (ord >= num_devices)
+ gomp_fatal ("device %u out of range", ord);
- /* If we're changing the device number, de-associate this thread with
- the device (but don't close the device, since it may be in use by
- other threads). */
- if (thr && thr->dev && n != thr->dev->target_id)
- thr->dev = NULL;
+ acc_dev = &base_dev[ord];
- lazy_open (n);
+ if (!acc_dev->is_initialized)
+ gomp_init_device (acc_dev);
gomp_mutex_unlock (&acc_device_lock);
+
+ goacc_attach_host_thread_to_device (ord);
}
+
+ goacc_device_num = ord;
}
ialias (acc_set_device_num)
@@ -554,10 +548,7 @@ ialias (acc_set_device_num)
int
acc_on_device (acc_device_t dev)
{
- struct goacc_thread *thr = goacc_thread ();
-
- if (thr && thr->dev
- && acc_device_type (thr->dev->type) == acc_device_host_nonshm)
+ if (acc_get_device_type () == acc_device_host_nonshm)
return dev == acc_device_host_nonshm || dev == acc_device_not_host;
/* Just rely on the compiler builtin. */
@@ -577,7 +568,7 @@ goacc_runtime_initialize (void)
pthread_key_create (&goacc_cleanup_key, goacc_destroy_thread);
- base_dev = NULL;
+ cached_base_dev = NULL;
goacc_threads = NULL;
gomp_mutex_init (&goacc_thread_lock);
@@ -606,9 +597,8 @@ goacc_restore_bind (void)
}
/* This is called from any OpenACC support function that may need to implicitly
- initialize the libgomp runtime. On exit all such initialization will have
- been done, and both the global ACC_dev and the per-host-thread ACC_memmap
- pointers will be valid. */
+ initialize the libgomp runtime, either globally or from a new host thread.
+ On exit "goacc_thread" will return a valid & populated thread block. */
attribute_hidden void
goacc_lazy_initialize (void)
@@ -618,12 +608,8 @@ goacc_lazy_initialize (void)
if (thr && thr->dev)
return;
- if (!base_dev)
- lazy_init_and_open (acc_device_default);
+ if (!cached_base_dev)
+ acc_init (acc_device_default);
else
- {
- gomp_mutex_lock (&acc_device_lock);
- lazy_open (-1);
- gomp_mutex_unlock (&acc_device_lock);
- }
+ goacc_attach_host_thread_to_device (-1);
}