diff options
author | Julian Brown <julian@codesourcery.com> | 2015-04-08 15:58:33 +0000 |
---|---|---|
committer | Julian Brown <jules@gcc.gnu.org> | 2015-04-08 15:58:33 +0000 |
commit | d93bdab53b8de8677bca3af17fe8072458ea3f6b (patch) | |
tree | 60d71a75181c79b311aaa199f917cb19ed8c06f7 /libgomp/oacc-init.c | |
parent | a6330e856f5f2a0c6c92e54cec42ff1798bf0ea8 (diff) | |
download | gcc-d93bdab53b8de8677bca3af17fe8072458ea3f6b.zip gcc-d93bdab53b8de8677bca3af17fe8072458ea3f6b.tar.gz gcc-d93bdab53b8de8677bca3af17fe8072458ea3f6b.tar.bz2 |
mkoffload.c (process): Support variable mapping.
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.
From-SVN: r221922
Diffstat (limited to 'libgomp/oacc-init.c')
-rw-r--r-- | libgomp/oacc-init.c | 424 |
1 files changed, 205 insertions, 219 deletions
diff --git a/libgomp/oacc-init.c b/libgomp/oacc-init.c index 1e0243e..dc40fb6 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); } |