aboutsummaryrefslogtreecommitdiff
path: root/libgomp
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@codesourcery.com>2019-12-22 19:54:09 +0000
committerFrederik Harwath <frederik@gcc.gnu.org>2019-12-22 19:54:09 +0000
commit6c84c8bf9b29ce89f5d263c1fa3630896fcb23f4 (patch)
tree0e15cf12a4c3396702ed004deabe3c86ea7ac18e /libgomp
parentedadb8adc3563bf782e4781bf3be6425af566368 (diff)
downloadgcc-6c84c8bf9b29ce89f5d263c1fa3630896fcb23f4.zip
gcc-6c84c8bf9b29ce89f5d263c1fa3630896fcb23f4.tar.gz
gcc-6c84c8bf9b29ce89f5d263c1fa3630896fcb23f4.tar.bz2
Add OpenACC 2.6 `acc_get_property' support
Add generic support for the OpenACC 2.6 `acc_get_property' and `acc_get_property_string' routines, as well as full handlers for the host and the NVPTX offload targets and minimal handlers for the HSA, Intel MIC, and AMD GCN offload targets. Included are C/C++ and Fortran tests that, in particular, print the property values for acc_property_vendor, acc_property_memory, acc_property_free_memory, acc_property_name, and acc_property_driver. The output looks as follows: Vendor: GNU Name: GOMP Total memory: 0 Free memory: 0 Driver: 1.0 with the host driver (where the memory related properties are not supported for the host device and yield 0, conforming to the standard) and output like: Vendor: Nvidia Total memory: 12651462656 Free memory: 12202737664 Name: TITAN V Driver: CUDA Driver 9.1 with the NVPTX driver. 2019-12-22 Maciej W. Rozycki <macro@codesourcery.com> Frederik Harwath <frederik@codesourcery.com> Thomas Schwinge <tschwinge@codesourcery.com> include/ * gomp-constants.h (gomp_device_property): New enum. libgomp/ * libgomp.h (gomp_device_descr): Add `get_property_func' member. * libgomp-plugin.h (gomp_device_property_value): New union. (gomp_device_property_value): New prototype. * openacc.h (acc_device_t): Add `acc_device_current' enumeration constant. (acc_device_property_t): New enum. (acc_get_property, acc_get_property_string): New prototypes. * oacc-init.c (acc_get_device_type): Also assert that result is not `acc_device_current'. (get_property_any, acc_get_property, acc_get_property_string): New functions. * openacc.f90 (openacc_kinds): Add `acc_device_current' and `acc_property_memory', `acc_property_free_memory', `acc_property_name', `acc_property_vendor' and `acc_property_driver' constants. Add `acc_device_property' data type. (openacc_internal): Add `acc_get_property' and `acc_get_property_string' interfaces. Add `acc_get_property_h', `acc_get_property_string_h', `acc_get_property_l' and `acc_get_property_string_l'. * oacc-host.c (host_get_property): New function. (host_dispatch): Wire it. * target.c (gomp_load_plugin_for_device): Handle `get_property'. * libgomp.map (OACC_2.6): Add `acc_get_property', `acc_get_property_h_', `acc_get_property_string' and `acc_get_property_string_h_' symbols. * libgomp.texi (OpenACC Runtime Library Routines): Add `acc_get_property'. (acc_get_property): New node. * plugin/plugin-gcn.c (GOMP_OFFLOAD_get_property): New function (stub). * plugin/plugin-hsa.c (GOMP_OFFLOAD_get_property): New function. * plugin/plugin-nvptx.c (CUDA_CALLS): Add `cuDeviceGetName', `cuDeviceTotalMem', `cuDriverGetVersion' and `cuMemGetInfo' calls. (GOMP_OFFLOAD_get_property): New function. (struct ptx_device): Add new field "name". (cuda_driver_version_s): Add new static variable ... (nvptx_init): ... and init from here. * testsuite/libgomp.oacc-c-c++-common/acc_get_property.c: New test. * testsuite/libgomp.oacc-c-c++-common/acc_get_property-2.c: New test. * testsuite/libgomp.oacc-c-c++-common/acc_get_property-3.c: New test. * testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c: New file with test helper functions. * testsuite/libgomp.oacc-fortran/acc_get_property.f90: New test. liboffloadmic/ * plugin/libgomp-plugin-intelmic.cpp (GOMP_OFFLOAD_get_property): New function. Reviewed-by: Thomas Schwinge <thomas@codesourcery.com> Co-Authored-By: Frederik Harwath <frederik@codesourcery.com> Co-Authored-By: Thomas Schwinge <tschwinge@codesourcery.com> From-SVN: r279710
Diffstat (limited to 'libgomp')
-rw-r--r--libgomp/ChangeLog51
-rw-r--r--libgomp/libgomp-plugin.h8
-rw-r--r--libgomp/libgomp.h1
-rw-r--r--libgomp/libgomp.map4
-rw-r--r--libgomp/libgomp.texi39
-rw-r--r--libgomp/oacc-host.c22
-rw-r--r--libgomp/oacc-init.c63
-rw-r--r--libgomp/openacc.f90129
-rw-r--r--libgomp/openacc.h15
-rw-r--r--libgomp/plugin/cuda-lib.def4
-rw-r--r--libgomp/plugin/plugin-gcn.c11
-rw-r--r--libgomp/plugin/plugin-hsa.c26
-rw-r--r--libgomp/plugin/plugin-nvptx.c87
-rw-r--r--libgomp/target.c1
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-2.c68
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-3.c19
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c80
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property.c76
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/acc_get_property.f9093
19 files changed, 791 insertions, 6 deletions
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index c557aa4..deaff15 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,54 @@
+2019-12-22 Maciej W. Rozycki <macro@codesourcery.com>
+ Frederik Harwath <frederik@codesourcery.com>
+ Thomas Schwinge <tschwinge@codesourcery.com>
+
+ * libgomp.h (gomp_device_descr): Add `get_property_func' member.
+ * libgomp-plugin.h (gomp_device_property_value): New union.
+ (gomp_device_property_value): New prototype.
+ * openacc.h (acc_device_t): Add `acc_device_current' enumeration
+ constant.
+ (acc_device_property_t): New enum.
+ (acc_get_property, acc_get_property_string): New prototypes.
+ * oacc-init.c (acc_get_device_type): Also assert that result
+ is not `acc_device_current'.
+ (get_property_any, acc_get_property, acc_get_property_string):
+ New functions.
+ * openacc.f90 (openacc_kinds): Add `acc_device_current' and
+ `acc_property_memory', `acc_property_free_memory',
+ `acc_property_name', `acc_property_vendor' and
+ `acc_property_driver' constants. Add `acc_device_property' data
+ type.
+ (openacc_internal): Add `acc_get_property' and
+ `acc_get_property_string' interfaces. Add `acc_get_property_h',
+ `acc_get_property_string_h', `acc_get_property_l' and
+ `acc_get_property_string_l'.
+ * oacc-host.c (host_get_property): New function.
+ (host_dispatch): Wire it.
+ * target.c (gomp_load_plugin_for_device): Handle `get_property'.
+ * libgomp.map (OACC_2.6): Add `acc_get_property', `acc_get_property_h_',
+ `acc_get_property_string' and `acc_get_property_string_h_' symbols.
+ * libgomp.texi (OpenACC Runtime Library Routines): Add
+ `acc_get_property'.
+ (acc_get_property): New node.
+ * plugin/plugin-gcn.c (GOMP_OFFLOAD_get_property): New
+ function (stub).
+ * plugin/plugin-hsa.c (GOMP_OFFLOAD_get_property): New function.
+ * plugin/plugin-nvptx.c (CUDA_CALLS): Add `cuDeviceGetName',
+ `cuDeviceTotalMem', `cuDriverGetVersion' and `cuMemGetInfo'
+ calls.
+ (GOMP_OFFLOAD_get_property): New function.
+ (struct ptx_device): Add new field "name".
+ (cuda_driver_version_s): Add new static variable ...
+ (nvptx_init): ... and init from here.
+
+ * testsuite/libgomp.oacc-c-c++-common/acc_get_property.c: New test.
+ * testsuite/libgomp.oacc-c-c++-common/acc_get_property-2.c: New test.
+ * testsuite/libgomp.oacc-c-c++-common/acc_get_property-3.c: New test.
+ * testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c: New file
+ with test helper functions.
+
+ * testsuite/libgomp.oacc-fortran/acc_get_property.f90: New test.
+
2019-12-22 Maciej W. Rozycki <macro@wdc.com>
* testsuite/libgomp-test-support.exp.in (GCC_UNDER_TEST): New
diff --git a/libgomp/libgomp-plugin.h b/libgomp/libgomp-plugin.h
index 037558c..d3c6dc3 100644
--- a/libgomp/libgomp-plugin.h
+++ b/libgomp/libgomp-plugin.h
@@ -54,6 +54,13 @@ enum offload_target_type
OFFLOAD_TARGET_TYPE_GCN = 8
};
+/* Container type for passing device properties. */
+union gomp_device_property_value
+{
+ const char *ptr;
+ size_t val;
+};
+
/* Opaque type to represent plugin-dependent implementation of an
OpenACC asynchronous queue. */
struct goacc_asyncqueue;
@@ -94,6 +101,7 @@ extern const char *GOMP_OFFLOAD_get_name (void);
extern unsigned int GOMP_OFFLOAD_get_caps (void);
extern int GOMP_OFFLOAD_get_type (void);
extern int GOMP_OFFLOAD_get_num_devices (void);
+extern union gomp_device_property_value GOMP_OFFLOAD_get_property (int, int);
extern bool GOMP_OFFLOAD_init_device (int);
extern bool GOMP_OFFLOAD_fini_device (int);
extern unsigned GOMP_OFFLOAD_version (void);
diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h
index c965357..24c7669 100644
--- a/libgomp/libgomp.h
+++ b/libgomp/libgomp.h
@@ -1113,6 +1113,7 @@ struct gomp_device_descr
__typeof (GOMP_OFFLOAD_get_caps) *get_caps_func;
__typeof (GOMP_OFFLOAD_get_type) *get_type_func;
__typeof (GOMP_OFFLOAD_get_num_devices) *get_num_devices_func;
+ __typeof (GOMP_OFFLOAD_get_property) *get_property_func;
__typeof (GOMP_OFFLOAD_init_device) *init_device_func;
__typeof (GOMP_OFFLOAD_fini_device) *fini_device_func;
__typeof (GOMP_OFFLOAD_version) *version_func;
diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index 63276f7..c7268bf 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -492,6 +492,10 @@ OACC_2.6 {
acc_detach_async;
acc_detach_finalize;
acc_detach_finalize_async;
+ acc_get_property;
+ acc_get_property_h_;
+ acc_get_property_string;
+ acc_get_property_string_h_;
} OACC_2.5.1;
GOACC_2.0 {
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index ac9d38e..5f8f1be 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -1849,6 +1849,7 @@ acceleration device.
* acc_get_device_type:: Get type of device accelerator to be used.
* acc_set_device_num:: Set device number to use.
* acc_get_device_num:: Get device number to be used.
+* acc_get_property:: Get device property.
* acc_async_test:: Tests for completion of a specific asynchronous
operation.
* acc_async_test_all:: Tests for completion of all asychronous
@@ -2038,6 +2039,44 @@ region.
+@node acc_get_property
+@section @code{acc_get_property} -- Get device property.
+@cindex acc_get_property
+@cindex acc_get_property_string
+@table @asis
+@item @emph{Description}
+These routines return the value of the specified @var{property} for the
+device being queried according to @var{devicenum} and @var{devicetype}.
+Integer-valued and string-valued properties are returned by
+@code{acc_get_property} and @code{acc_get_property_string} respectively.
+The Fortran @code{acc_get_property_string} subroutine returns the string
+retrieved in its fourth argument while the remaining entry points are
+functions, which pass the return value as their result.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{size_t acc_get_property(int devicenum, acc_device_t devicetype, acc_device_property_t property);}
+@item @emph{Prototype}: @tab @code{const char *acc_get_property_string(int devicenum, acc_device_t devicetype, acc_device_property_t property);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{function acc_get_property(devicenum, devicetype, property)}
+@item @emph{Interface}: @tab @code{subroutine acc_get_property_string(devicenum, devicetype, property, string)}
+@item @tab @code{integer devicenum}
+@item @tab @code{integer(kind=acc_device_kind) devicetype}
+@item @tab @code{integer(kind=acc_device_property) property}
+@item @tab @code{integer(kind=acc_device_property) acc_get_property}
+@item @tab @code{character(*) string}
+@end multitable
+
+@item @emph{Reference}:
+@uref{https://www.openacc.org, OpenACC specification v2.6}, section
+3.2.6.
+@end table
+
+
+
@node acc_async_test
@section @code{acc_async_test} -- Test for completion of a specific asynchronous operation.
@table @asis
diff --git a/libgomp/oacc-host.c b/libgomp/oacc-host.c
index 845140f..ec9e324 100644
--- a/libgomp/oacc-host.c
+++ b/libgomp/oacc-host.c
@@ -59,6 +59,27 @@ host_get_num_devices (void)
return 1;
}
+static union gomp_device_property_value
+host_get_property (int n, int prop)
+{
+ union gomp_device_property_value nullval = { .val = 0 };
+
+ if (n >= host_get_num_devices ())
+ return nullval;
+
+ switch (prop)
+ {
+ case GOMP_DEVICE_PROPERTY_NAME:
+ return (union gomp_device_property_value) { .ptr = "GOMP" };
+ case GOMP_DEVICE_PROPERTY_VENDOR:
+ return (union gomp_device_property_value) { .ptr = "GNU" };
+ case GOMP_DEVICE_PROPERTY_DRIVER:
+ return (union gomp_device_property_value) { .ptr = VERSION };
+ default:
+ return nullval;
+ }
+}
+
static bool
host_init_device (int n __attribute__ ((unused)))
{
@@ -248,6 +269,7 @@ static struct gomp_device_descr host_dispatch =
.get_caps_func = host_get_caps,
.get_type_func = host_get_type,
.get_num_devices_func = host_get_num_devices,
+ .get_property_func = host_get_property,
.init_device_func = host_init_device,
.fini_device_func = host_fini_device,
.version_func = host_version,
diff --git a/libgomp/oacc-init.c b/libgomp/oacc-init.c
index dd88b58..487a2cc 100644
--- a/libgomp/oacc-init.c
+++ b/libgomp/oacc-init.c
@@ -670,7 +670,8 @@ acc_get_device_type (void)
}
assert (res != acc_device_default
- && res != acc_device_not_host);
+ && res != acc_device_not_host
+ && res != acc_device_current);
return res;
}
@@ -759,6 +760,66 @@ acc_set_device_num (int ord, acc_device_t d)
ialias (acc_set_device_num)
+static union gomp_device_property_value
+get_property_any (int ord, acc_device_t d, acc_device_property_t prop)
+{
+ goacc_lazy_initialize ();
+ struct goacc_thread *thr = goacc_thread ();
+
+ if (d == acc_device_current && thr && thr->dev)
+ return thr->dev->get_property_func (thr->dev->target_id, prop);
+
+ gomp_mutex_lock (&acc_device_lock);
+
+ struct gomp_device_descr *dev = resolve_device (d, true);
+
+ int num_devices = dev->get_num_devices_func ();
+
+ if (num_devices <= 0 || ord >= num_devices)
+ acc_dev_num_out_of_range (d, ord, num_devices);
+
+ dev += ord;
+
+ gomp_mutex_lock (&dev->lock);
+ if (dev->state == GOMP_DEVICE_UNINITIALIZED)
+ gomp_init_device (dev);
+ gomp_mutex_unlock (&dev->lock);
+
+ gomp_mutex_unlock (&acc_device_lock);
+
+ assert (dev);
+
+ return dev->get_property_func (dev->target_id, prop);
+}
+
+size_t
+acc_get_property (int ord, acc_device_t d, acc_device_property_t prop)
+{
+ if (!known_device_type_p (d))
+ unknown_device_type_error(d);
+
+ if (prop & GOMP_DEVICE_PROPERTY_STRING_MASK)
+ return 0;
+ else
+ return get_property_any (ord, d, prop).val;
+}
+
+ialias (acc_get_property)
+
+const char *
+acc_get_property_string (int ord, acc_device_t d, acc_device_property_t prop)
+{
+ if (!known_device_type_p (d))
+ unknown_device_type_error(d);
+
+ if (prop & GOMP_DEVICE_PROPERTY_STRING_MASK)
+ return get_property_any (ord, d, prop).ptr;
+ else
+ return NULL;
+}
+
+ialias (acc_get_property_string)
+
/* For -O and higher, the compiler always attempts to expand acc_on_device, but
if the user disables the builtin, or calls it via a pointer, we'll need this
version.
diff --git a/libgomp/openacc.f90 b/libgomp/openacc.f90
index fb7fc6e..e5b4b40 100644
--- a/libgomp/openacc.f90
+++ b/libgomp/openacc.f90
@@ -31,16 +31,18 @@
module openacc_kinds
use iso_fortran_env, only: int32
+ use iso_c_binding, only: c_size_t
implicit none
public
- private :: int32
+ private :: int32, c_size_t
! When adding items, also update 'public' setting in 'module openacc' below.
integer, parameter :: acc_device_kind = int32
! Keep in sync with include/gomp-constants.h.
+ integer (acc_device_kind), parameter :: acc_device_current = -3
integer (acc_device_kind), parameter :: acc_device_none = 0
integer (acc_device_kind), parameter :: acc_device_default = 1
integer (acc_device_kind), parameter :: acc_device_host = 2
@@ -49,6 +51,15 @@ module openacc_kinds
integer (acc_device_kind), parameter :: acc_device_nvidia = 5
integer (acc_device_kind), parameter :: acc_device_gcn = 8
+ integer, parameter :: acc_device_property = c_size_t
+
+ ! Keep in sync with include/gomp-constants.h.
+ integer (acc_device_property), parameter :: acc_property_memory = 1
+ integer (acc_device_property), parameter :: acc_property_free_memory = 2
+ integer (acc_device_property), parameter :: acc_property_name = int(Z'10001')
+ integer (acc_device_property), parameter :: acc_property_vendor = int(Z'10002')
+ integer (acc_device_property), parameter :: acc_property_driver = int(Z'10003')
+
integer, parameter :: acc_handle_kind = int32
! Keep in sync with include/gomp-constants.h.
@@ -89,6 +100,24 @@ module openacc_internal
integer (acc_device_kind) d
end function
+ function acc_get_property_h (n, d, p)
+ import
+ implicit none (type, external)
+ integer (acc_device_property) :: acc_get_property_h
+ integer, value :: n
+ integer (acc_device_kind), value :: d
+ integer (acc_device_property), value :: p
+ end function
+
+ subroutine acc_get_property_string_h (n, d, p, s)
+ import
+ implicit none (type, external)
+ integer, value :: n
+ integer (acc_device_kind), value :: d
+ integer (acc_device_property), value :: p
+ character (*) :: s
+ end subroutine
+
function acc_async_test_h (a)
logical acc_async_test_h
integer a
@@ -508,6 +537,26 @@ module openacc_internal
integer (c_int), value :: d
end function
+ function acc_get_property_l (n, d, p) &
+ bind (C, name = "acc_get_property")
+ use iso_c_binding, only: c_int, c_size_t
+ implicit none (type, external)
+ integer (c_size_t) :: acc_get_property_l
+ integer (c_int), value :: n
+ integer (c_int), value :: d
+ integer (c_int), value :: p
+ end function
+
+ function acc_get_property_string_l (n, d, p) &
+ bind (C, name = "acc_get_property_string")
+ use iso_c_binding, only: c_int, c_ptr
+ implicit none (type, external)
+ type (c_ptr) :: acc_get_property_string_l
+ integer (c_int), value :: n
+ integer (c_int), value :: d
+ integer (c_int), value :: p
+ end function
+
function acc_async_test_l (a) &
bind (C, name = "acc_async_test")
use iso_c_binding, only: c_int
@@ -716,16 +765,23 @@ module openacc
private
! From openacc_kinds
- public :: acc_device_kind, acc_handle_kind
+ public :: acc_device_kind
public :: acc_device_none, acc_device_default, acc_device_host
public :: acc_device_not_host, acc_device_nvidia, acc_device_gcn
+
+ public :: acc_device_property
+ public :: acc_property_memory, acc_property_free_memory
+ public :: acc_property_name, acc_property_vendor, acc_property_driver
+
+ public :: acc_handle_kind
public :: acc_async_noval, acc_async_sync
public :: openacc_version
public :: acc_get_num_devices, acc_set_device_type, acc_get_device_type
- public :: acc_set_device_num, acc_get_device_num, acc_async_test
- public :: acc_async_test_all
+ public :: acc_set_device_num, acc_get_device_num
+ public :: acc_get_property, acc_get_property_string
+ public :: acc_async_test, acc_async_test_all
public :: acc_wait, acc_async_wait, acc_wait_async
public :: acc_wait_all, acc_async_wait_all, acc_wait_all_async
public :: acc_init, acc_shutdown, acc_on_device
@@ -758,6 +814,14 @@ module openacc
procedure :: acc_get_device_num_h
end interface
+ interface acc_get_property
+ procedure :: acc_get_property_h
+ end interface
+
+ interface acc_get_property_string
+ procedure :: acc_get_property_string_h
+ end interface
+
interface acc_async_test
procedure :: acc_async_test_h
end interface
@@ -976,6 +1040,63 @@ function acc_get_device_num_h (d)
acc_get_device_num_h = acc_get_device_num_l (d)
end function
+function acc_get_property_h (n, d, p)
+ use iso_c_binding, only: c_int, c_size_t
+ use openacc_internal, only: acc_get_property_l
+ use openacc_kinds
+ implicit none (type, external)
+ integer (acc_device_property) :: acc_get_property_h
+ integer, value :: n
+ integer (acc_device_kind), value :: d
+ integer (acc_device_property), value :: p
+
+ integer (c_int) :: pint
+
+ pint = int (p, c_int)
+ acc_get_property_h = acc_get_property_l (n, d, pint)
+end function
+
+subroutine acc_get_property_string_h (n, d, p, s)
+ use iso_c_binding, only: c_char, c_int, c_ptr, c_f_pointer, c_associated
+ use openacc_internal, only: acc_get_property_string_l
+ use openacc_kinds
+ implicit none (type, external)
+ integer, value :: n
+ integer (acc_device_kind), value :: d
+ integer (acc_device_property), value :: p
+ character (*) :: s
+
+ integer (c_int) :: pint
+ type (c_ptr) :: cptr
+ integer :: clen
+ character (kind=c_char, len=1), pointer, contiguous :: sptr (:)
+ integer :: slen
+ integer :: i
+
+ interface
+ function strlen (s) bind (C, name = "strlen")
+ use iso_c_binding, only: c_ptr, c_size_t
+ type (c_ptr), intent(in), value :: s
+ integer (c_size_t) :: strlen
+ end function strlen
+ end interface
+
+ pint = int (p, c_int)
+ cptr = acc_get_property_string_l (n, d, pint)
+ s = ""
+ if (.not. c_associated (cptr)) then
+ return
+ end if
+
+ clen = int (strlen (cptr))
+ call c_f_pointer (cptr, sptr, [clen])
+
+ slen = min (clen, len (s))
+ do i = 1, slen
+ s (i:i) = sptr (i)
+ end do
+end subroutine
+
function acc_async_test_h (a)
use openacc_internal, only: acc_async_test_l
logical acc_async_test_h
diff --git a/libgomp/openacc.h b/libgomp/openacc.h
index d2e5c10..9b14306 100644
--- a/libgomp/openacc.h
+++ b/libgomp/openacc.h
@@ -49,6 +49,7 @@ extern "C" {
/* Types */
typedef enum acc_device_t {
/* Keep in sync with include/gomp-constants.h. */
+ acc_device_current = -3,
acc_device_none = 0,
acc_device_default = 1,
acc_device_host = 2,
@@ -62,6 +63,16 @@ typedef enum acc_device_t {
_ACC_neg = -1
} acc_device_t;
+typedef enum acc_device_property_t {
+ /* Keep in sync with include/gomp-constants.h. */
+ /* Start from 1 to catch uninitialized use. */
+ acc_property_memory = 1,
+ acc_property_free_memory = 2,
+ acc_property_name = 0x10001,
+ acc_property_vendor = 0x10002,
+ acc_property_driver = 0x10003
+} acc_device_property_t;
+
typedef enum acc_async_t {
/* Keep in sync with include/gomp-constants.h. */
acc_async_noval = -1,
@@ -73,6 +84,10 @@ void acc_set_device_type (acc_device_t) __GOACC_NOTHROW;
acc_device_t acc_get_device_type (void) __GOACC_NOTHROW;
void acc_set_device_num (int, acc_device_t) __GOACC_NOTHROW;
int acc_get_device_num (acc_device_t) __GOACC_NOTHROW;
+size_t acc_get_property
+ (int, acc_device_t, acc_device_property_t) __GOACC_NOTHROW;
+const char *acc_get_property_string
+ (int, acc_device_t, acc_device_property_t) __GOACC_NOTHROW;
int acc_async_test (int) __GOACC_NOTHROW;
int acc_async_test_all (void) __GOACC_NOTHROW;
void acc_wait (int) __GOACC_NOTHROW;
diff --git a/libgomp/plugin/cuda-lib.def b/libgomp/plugin/cuda-lib.def
index a16badc..cd91b39 100644
--- a/libgomp/plugin/cuda-lib.def
+++ b/libgomp/plugin/cuda-lib.def
@@ -8,6 +8,9 @@ CUDA_ONE_CALL (cuCtxSynchronize)
CUDA_ONE_CALL (cuDeviceGet)
CUDA_ONE_CALL (cuDeviceGetAttribute)
CUDA_ONE_CALL (cuDeviceGetCount)
+CUDA_ONE_CALL (cuDeviceGetName)
+CUDA_ONE_CALL (cuDeviceTotalMem)
+CUDA_ONE_CALL (cuDriverGetVersion)
CUDA_ONE_CALL (cuEventCreate)
CUDA_ONE_CALL (cuEventDestroy)
CUDA_ONE_CALL (cuEventElapsedTime)
@@ -35,6 +38,7 @@ CUDA_ONE_CALL (cuMemcpyHtoDAsync)
CUDA_ONE_CALL (cuMemFree)
CUDA_ONE_CALL (cuMemFreeHost)
CUDA_ONE_CALL (cuMemGetAddressRange)
+CUDA_ONE_CALL (cuMemGetInfo)
CUDA_ONE_CALL (cuMemHostGetDevicePointer)
CUDA_ONE_CALL (cuModuleGetFunction)
CUDA_ONE_CALL (cuModuleGetGlobal)
diff --git a/libgomp/plugin/plugin-gcn.c b/libgomp/plugin/plugin-gcn.c
index 04fe472..32239c7 100644
--- a/libgomp/plugin/plugin-gcn.c
+++ b/libgomp/plugin/plugin-gcn.c
@@ -3236,6 +3236,17 @@ GOMP_OFFLOAD_get_num_devices (void)
return hsa_context.agent_count;
}
+union gomp_device_property_value
+GOMP_OFFLOAD_get_property (int device, int prop)
+{
+ /* Stub. Check device and return default value for unsupported properties. */
+ /* TODO: Implement this function. */
+ get_agent_info (device);
+
+ union gomp_device_property_value nullval = { .val = 0 };
+ return nullval;
+}
+
/* Initialize device (agent) number N so that it can be used for computation.
Return TRUE on success. */
diff --git a/libgomp/plugin/plugin-hsa.c b/libgomp/plugin/plugin-hsa.c
index 409e138..259f704 100644
--- a/libgomp/plugin/plugin-hsa.c
+++ b/libgomp/plugin/plugin-hsa.c
@@ -699,6 +699,32 @@ GOMP_OFFLOAD_get_num_devices (void)
return hsa_context.agent_count;
}
+/* Part of the libgomp plugin interface. Return the value of property
+ PROP of agent number N. */
+
+union gomp_device_property_value
+GOMP_OFFLOAD_get_property (int n, int prop)
+{
+ union gomp_device_property_value nullval = { .val = 0 };
+
+ if (!init_hsa_context ())
+ return nullval;
+ if (n >= hsa_context.agent_count)
+ {
+ GOMP_PLUGIN_error
+ ("Request for a property of a non-existing HSA device %i", n);
+ return nullval;
+ }
+
+ switch (prop)
+ {
+ case GOMP_DEVICE_PROPERTY_VENDOR:
+ return (union gomp_device_property_value) { .ptr = "HSA" };
+ default:
+ return nullval;
+ }
+}
+
/* Part of the libgomp plugin interface. Initialize agent number N so that it
can be used for computation. Return TRUE on success. */
diff --git a/libgomp/plugin/plugin-nvptx.c b/libgomp/plugin/plugin-nvptx.c
index 911d0f6..80e5475 100644
--- a/libgomp/plugin/plugin-nvptx.c
+++ b/libgomp/plugin/plugin-nvptx.c
@@ -189,6 +189,10 @@ cuda_error (CUresult r)
return fallback;
}
+/* Version of the CUDA Toolkit in the same MAJOR.MINOR format that is used by
+ Nvidia, such as in the 'deviceQuery' program (Nvidia's CUDA samples). */
+static char cuda_driver_version_s[30];
+
static unsigned int instantiated_devices = 0;
static pthread_mutex_t ptx_dev_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -284,7 +288,7 @@ struct ptx_device
bool map;
bool concur;
bool mkern;
- int mode;
+ int mode;
int clock_khz;
int num_sms;
int regs_per_block;
@@ -294,6 +298,9 @@ struct ptx_device
int max_threads_per_multiprocessor;
int default_dims[GOMP_DIM_MAX];
+ /* Length as used by the CUDA Runtime API ('struct cudaDeviceProp'). */
+ char name[256];
+
struct ptx_image_data *images; /* Images loaded on device. */
pthread_mutex_t image_lock; /* Lock for above list. */
@@ -327,9 +334,16 @@ nvptx_init (void)
CUDA_CALL (cuInit, 0);
+ int cuda_driver_version;
+ CUDA_CALL_ERET (NULL, cuDriverGetVersion, &cuda_driver_version);
+ snprintf (cuda_driver_version_s, sizeof cuda_driver_version_s,
+ "CUDA Driver %u.%u",
+ cuda_driver_version / 1000, cuda_driver_version % 1000 / 10);
+
CUDA_CALL (cuDeviceGetCount, &ndevs);
ptx_devices = GOMP_PLUGIN_malloc_cleared (sizeof (struct ptx_device *)
* ndevs);
+
return true;
}
@@ -491,6 +505,9 @@ nvptx_open_device (int n)
for (int i = 0; i != GOMP_DIM_MAX; i++)
ptx_dev->default_dims[i] = 0;
+ CUDA_CALL_ERET (NULL, cuDeviceGetName, ptx_dev->name, sizeof ptx_dev->name,
+ dev);
+
ptx_dev->images = NULL;
pthread_mutex_init (&ptx_dev->image_lock, NULL);
@@ -1104,6 +1121,74 @@ GOMP_OFFLOAD_get_num_devices (void)
return nvptx_get_num_devices ();
}
+union gomp_device_property_value
+GOMP_OFFLOAD_get_property (int n, int prop)
+{
+ union gomp_device_property_value propval = { .val = 0 };
+
+ pthread_mutex_lock (&ptx_dev_lock);
+
+ if (n >= nvptx_get_num_devices () || n < 0 || ptx_devices[n] == NULL)
+ {
+ pthread_mutex_unlock (&ptx_dev_lock);
+ return propval;
+ }
+
+ struct ptx_device *ptx_dev = ptx_devices[n];
+ switch (prop)
+ {
+ case GOMP_DEVICE_PROPERTY_MEMORY:
+ {
+ size_t total_mem;
+
+ CUDA_CALL_ERET (propval, cuDeviceTotalMem, &total_mem, ptx_dev->dev);
+ propval.val = total_mem;
+ }
+ break;
+ case GOMP_DEVICE_PROPERTY_FREE_MEMORY:
+ {
+ size_t total_mem;
+ size_t free_mem;
+ CUdevice ctxdev;
+
+ CUDA_CALL_ERET (propval, cuCtxGetDevice, &ctxdev);
+ if (ptx_dev->dev == ctxdev)
+ CUDA_CALL_ERET (propval, cuMemGetInfo, &free_mem, &total_mem);
+ else if (ptx_dev->ctx)
+ {
+ CUcontext old_ctx;
+
+ CUDA_CALL_ERET (propval, cuCtxPushCurrent, ptx_dev->ctx);
+ CUDA_CALL_ERET (propval, cuMemGetInfo, &free_mem, &total_mem);
+ CUDA_CALL_ASSERT (cuCtxPopCurrent, &old_ctx);
+ }
+ else
+ {
+ CUcontext new_ctx;
+
+ CUDA_CALL_ERET (propval, cuCtxCreate, &new_ctx, CU_CTX_SCHED_AUTO,
+ ptx_dev->dev);
+ CUDA_CALL_ERET (propval, cuMemGetInfo, &free_mem, &total_mem);
+ CUDA_CALL_ASSERT (cuCtxDestroy, new_ctx);
+ }
+ propval.val = free_mem;
+ }
+ break;
+ case GOMP_DEVICE_PROPERTY_NAME:
+ propval.ptr = ptx_dev->name;
+ break;
+ case GOMP_DEVICE_PROPERTY_VENDOR:
+ propval.ptr = "Nvidia";
+ break;
+ case GOMP_DEVICE_PROPERTY_DRIVER:
+ propval.ptr = cuda_driver_version_s;
+ break;
+ }
+
+ pthread_mutex_unlock (&ptx_dev_lock);
+ return propval;
+}
+
bool
GOMP_OFFLOAD_init_device (int n)
{
diff --git a/libgomp/target.c b/libgomp/target.c
index bf30716..3562c37 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -3001,6 +3001,7 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device,
DLSYM (get_caps);
DLSYM (get_type);
DLSYM (get_num_devices);
+ DLSYM (get_property);
DLSYM (init_device);
DLSYM (fini_device);
DLSYM (load_image);
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-2.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-2.c
new file mode 100644
index 0000000..4dd13c4
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-2.c
@@ -0,0 +1,68 @@
+/* Test the `acc_get_property' and '`acc_get_property_string' library
+ functions on Nvidia devices by comparing property values with
+ those obtained through the CUDA API. */
+/* { dg-additional-sources acc_get_property-aux.c } */
+/* { dg-additional-options "-lcuda -lcudart" } */
+/* { dg-do run { target openacc_nvidia_accel_selected } } */
+
+#include <openacc.h>
+#include <cuda.h>
+#include <cuda_runtime_api.h>
+#include <string.h>
+#include <stdio.h>
+
+void expect_device_properties
+(acc_device_t dev_type, int dev_num,
+ int expected_total_mem, int expected_free_mem,
+ const char* expected_vendor, const char* expected_name,
+ const char* expected_driver);
+
+int main ()
+{
+ int dev_count;
+ cudaGetDeviceCount (&dev_count);
+
+ for (int dev_num = 0; dev_num < dev_count; ++dev_num)
+ {
+ if (cudaSetDevice (dev_num) != cudaSuccess)
+ {
+ fprintf (stderr, "cudaSetDevice failed.\n");
+ abort ();
+ }
+
+ printf("Checking device %d\n", dev_num);
+
+ const char *vendor = "Nvidia";
+ size_t free_mem;
+ size_t total_mem;
+ if (cudaMemGetInfo(&free_mem, &total_mem) != cudaSuccess)
+ {
+ fprintf (stderr, "cudaMemGetInfo failed.\n");
+ abort ();
+ }
+
+ struct cudaDeviceProp p;
+ if (cudaGetDeviceProperties(&p, dev_num) != cudaSuccess)
+ {
+ fprintf (stderr, "cudaGetDeviceProperties failed.\n");
+ abort ();
+ }
+
+ int driver_version;
+ if (cudaDriverGetVersion(&driver_version) != cudaSuccess)
+ {
+ fprintf (stderr, "cudaDriverGetVersion failed.\n");
+ abort ();
+ }
+ /* The version string should contain the version of the CUDA Toolkit
+ in the same MAJOR.MINOR format that is used by Nvidia.
+ The format string below is the same that is used by the deviceQuery
+ program, which belongs to Nvidia's CUDA samples, to print the version. */
+ char driver[30];
+ snprintf (driver, sizeof driver, "CUDA Driver %u.%u",
+ driver_version / 1000, driver_version % 1000 / 10);
+
+ expect_device_properties(acc_device_nvidia, dev_num,
+ total_mem, free_mem, vendor, p.name, driver);
+ }
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-3.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-3.c
new file mode 100644
index 0000000..9256500
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-3.c
@@ -0,0 +1,19 @@
+/* Test the `acc_get_property' and '`acc_get_property_string' library
+ functions for the host device. */
+/* { dg-additional-sources acc_get_property-aux.c } */
+/* { dg-do run } */
+
+#include <openacc.h>
+#include <stdio.h>
+
+void expect_device_properties
+(acc_device_t dev_type, int dev_num,
+ int expected_total_mem, int expected_free_mem,
+ const char* expected_vendor, const char* expected_name,
+ const char* expected_driver);
+
+int main()
+{
+ printf ("Checking acc_device_host device properties\n");
+ expect_device_properties (acc_device_host, 0, 0, 0, "GNU", "GOMP", "1.0");
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c
new file mode 100644
index 0000000..952bdbf
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c
@@ -0,0 +1,80 @@
+/* Auxiliary functions for acc_get_property tests */
+/* { dg-do compile { target skip-all-targets } } */
+
+#include <openacc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+void expect_device_properties
+(acc_device_t dev_type, int dev_num,
+ int expected_total_mem, int expected_free_mem,
+ const char* expected_vendor, const char* expected_name,
+ const char* expected_driver)
+{
+ const char *vendor = acc_get_property_string (dev_num, dev_type,
+ acc_property_vendor);
+ if (strcmp (vendor, expected_vendor))
+ {
+ fprintf (stderr, "Expected acc_property_vendor to equal \"%s\", "
+ "but was \"%s\".\n", expected_vendor, vendor);
+ abort ();
+ }
+
+ int total_mem = acc_get_property (dev_num, dev_type,
+ acc_property_memory);
+ if (total_mem != expected_total_mem)
+ {
+ fprintf (stderr, "Expected acc_property_memory to equal %d, "
+ "but was %d.\n", expected_total_mem, total_mem);
+ abort ();
+
+ }
+
+ int free_mem = acc_get_property (dev_num, dev_type,
+ acc_property_free_memory);
+ if (free_mem != expected_free_mem)
+ {
+ fprintf (stderr, "Expected acc_property_free_memory to equal %d, "
+ "but was %d.\n", expected_free_mem, free_mem);
+ abort ();
+ }
+
+ const char *name = acc_get_property_string (dev_num, dev_type,
+ acc_property_name);
+ if (strcmp (name, expected_name))
+ {
+ fprintf(stderr, "Expected acc_property_name to equal \"%s\", "
+ "but was \"%s\".\n", expected_name, name);
+ abort ();
+ }
+
+ const char *driver = acc_get_property_string (dev_num, dev_type,
+ acc_property_driver);
+ if (strcmp (expected_driver, driver))
+ {
+ fprintf (stderr, "Expected acc_property_driver to equal %s, "
+ "but was %s.\n", expected_driver, driver);
+ abort ();
+ }
+
+ int unknown_property = 16058;
+ int v = acc_get_property (dev_num, dev_type, (acc_device_property_t)unknown_property);
+ if (v != 0)
+ {
+ fprintf (stderr, "Expected value of unknown numeric property to equal 0, "
+ "but was %d.\n", v);
+ abort ();
+ }
+
+ int unknown_property2 = -16058;
+ const char *s = acc_get_property_string (dev_num, dev_type, (acc_device_property_t)unknown_property2);
+ if (s != NULL)
+ {
+ fprintf (stderr, "Expected value of unknown string property to be NULL, "
+ "but was %d.\n", s);
+ abort ();
+ }
+
+
+}
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property.c
new file mode 100644
index 0000000..289d1ba
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_get_property.c
@@ -0,0 +1,76 @@
+/* Test the `acc_get_property' and '`acc_get_property_string' library
+ functions by printing the results of those functions for all devices
+ of all device types mentioned in the OpenACC standard.
+
+ See also acc_get_property.f90. */
+/* { dg-do run { target { { ! { openacc_host_selected } } && { ! { openacc_amdgcn_accel_selected } } } } } */
+/* FIXME: This test does not work with the GCN implementation stub yet. */
+
+#include <openacc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Print the values of the properties of all devices of the given type
+ and do basic device independent validation. */
+
+void
+print_device_properties(acc_device_t type)
+{
+ const char *s;
+ size_t v;
+
+ int dev_count = acc_get_num_devices(type);
+
+ for (int i = 0; i < dev_count; ++i)
+ {
+ printf(" Device %d:\n", i+1);
+
+ s = acc_get_property_string (i, type, acc_property_vendor);
+ printf (" Vendor: %s\n", s);
+ if (s == NULL || *s == 0)
+ {
+ fprintf (stderr, "acc_property_vendor should not be null or empty.\n");
+ abort ();
+ }
+
+ v = acc_get_property (i, type, acc_property_memory);
+ printf (" Total memory: %zd\n", v);
+
+ v = acc_get_property (i, type, acc_property_free_memory);
+ printf (" Free memory: %zd\n", v);
+
+ s = acc_get_property_string (i, type, acc_property_name);
+ printf (" Name: %s\n", s);
+ if (s == NULL || *s == 0)
+ {
+ fprintf (stderr, "acc_property_name should not be null or empty.\n");
+ abort ();
+ }
+
+ s = acc_get_property_string (i, type, acc_property_driver);
+ printf (" Driver: %s\n", s);
+ if (s == NULL || *s == 0)
+ {
+ fprintf (stderr, "acc_property_string should not be null or empty.\n");
+ abort ();
+ }
+ }
+}
+
+int main ()
+{
+ printf("acc_device_none:\n");
+ /* For completness; not expected to print anything since there
+ should be no devices of this type. */
+ print_device_properties(acc_device_none);
+
+ printf("acc_device_default:\n");
+ print_device_properties(acc_device_default);
+
+ printf("acc_device_host:\n");
+ print_device_properties(acc_device_host);
+
+ printf("acc_device_not_host:\n");
+ print_device_properties(acc_device_not_host);
+}
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/acc_get_property.f90 b/libgomp/testsuite/libgomp.oacc-fortran/acc_get_property.f90
new file mode 100644
index 0000000..ce69547
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/acc_get_property.f90
@@ -0,0 +1,93 @@
+! Test the `acc_get_property' and '`acc_get_property_string' library
+! functions by printing the results of those functions for all devices
+! of all device types mentioned in the OpenACC standard.
+!
+! See also acc_get_property.c
+! { dg-do run { target { { ! { openacc_host_selected } } && { ! { openacc_amdgcn_accel_selected } } } } }
+! FIXME: This test does not work with the GCN implementation stub yet.
+
+program test
+ use openacc
+ implicit none
+
+ print *, "acc_device_none:"
+ ! For completeness; not expected to print anything
+ call print_device_properties (acc_device_none)
+
+ print *, "acc_device_default:"
+ call print_device_properties (acc_device_default)
+
+ print *, "acc_device_host:"
+ call print_device_properties (acc_device_host)
+
+ print *, "acc_device_not_host:"
+ call print_device_properties (acc_device_not_host)
+end program test
+
+! Print the values of the properties of all devices of the given type
+! and do basic device independent validation.
+subroutine print_device_properties (device_type)
+ use openacc
+ implicit none
+
+ integer, intent(in) :: device_type
+
+ integer :: device_count
+ integer :: device
+ integer(acc_device_property) :: v
+ character*256 :: s
+
+ device_count = acc_get_num_devices(device_type)
+
+ do device = 0, device_count - 1
+ print "(a, i0)", " Device ", device
+
+ call acc_get_property_string (device, device_type, acc_property_vendor, s)
+ print "(a, a)", " Vendor: ", trim (s)
+ if (s == "") then
+ print *, "acc_property_vendor should not be empty."
+ stop 1
+ end if
+
+ v = acc_get_property (device, device_type, acc_property_memory)
+ print "(a, i0)", " Total memory: ", v
+ if (v < 0) then
+ print *, "acc_property_memory should not be negative."
+ stop 1
+ end if
+
+ v = acc_get_property (device, device_type, acc_property_free_memory)
+ print "(a, i0)", " Free memory: ", v
+ if (v < 0) then
+ print *, "acc_property_free_memory should not to be negative."
+ stop 1
+ end if
+
+ v = acc_get_property (device, device_type, int(2360, kind = acc_device_property))
+ if (v /= 0) then
+ print *, "Value of unknown numeric property should be 0."
+ stop 1
+ end if
+
+ call acc_get_property_string (device, device_type, acc_property_name, s)
+ print "(a, a)", " Name: ", trim (s)
+ if (s == "") then
+ print *, "acc_property_name should not be empty."
+ stop 1
+ end if
+
+ call acc_get_property_string (device, device_type, acc_property_driver, s)
+ print "(a, a)", " Driver: ", trim (s)
+ if (s == "") then
+ print *, "acc_property_driver should not be empty."
+ stop 1
+ end if
+
+ call acc_get_property_string (device, device_type, int(4060, kind = acc_device_property), s)
+ if (s /= "") then
+ print *, "Value of unknown string property should be empty string."
+ stop 1
+ end if
+
+ end do
+end subroutine print_device_properties