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
This commit is contained in:
parent
edadb8adc3
commit
6c84c8bf9b
@ -1,3 +1,9 @@
|
||||
2019-12-22 Maciej W. Rozycki <macro@codesourcery.com>
|
||||
Frederik Harwath <frederik@codesourcery.com>
|
||||
Thomas Schwinge <tschwinge@codesourcery.com>
|
||||
|
||||
* gomp-constants.h (gomp_device_property): New enum.
|
||||
|
||||
2019-12-19 Julian Brown <julian@codesourcery.com>
|
||||
|
||||
* gomp-constants.h (gomp_map_kind): Add GOMP_MAP_ATTACH_DETACH.
|
||||
|
@ -195,6 +195,21 @@ enum gomp_map_kind
|
||||
#define GOMP_DEVICE_ICV -1
|
||||
#define GOMP_DEVICE_HOST_FALLBACK -2
|
||||
|
||||
/* Device property codes. Keep in sync with
|
||||
libgomp/{openacc.h,openacc.f90}:acc_device_property_t */
|
||||
/* Start from 1 to catch uninitialized use. */
|
||||
enum gomp_device_property
|
||||
{
|
||||
GOMP_DEVICE_PROPERTY_MEMORY = 1,
|
||||
GOMP_DEVICE_PROPERTY_FREE_MEMORY = 2,
|
||||
GOMP_DEVICE_PROPERTY_NAME = 0x10001,
|
||||
GOMP_DEVICE_PROPERTY_VENDOR = 0x10002,
|
||||
GOMP_DEVICE_PROPERTY_DRIVER = 0x10003
|
||||
};
|
||||
|
||||
/* Internal property mask to tell numeric and string values apart. */
|
||||
#define GOMP_DEVICE_PROPERTY_STRING_MASK 0x10000
|
||||
|
||||
/* GOMP_task/GOMP_taskloop* flags argument. */
|
||||
#define GOMP_TASK_FLAG_UNTIED (1 << 0)
|
||||
#define GOMP_TASK_FLAG_FINAL (1 << 1)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
93
libgomp/testsuite/libgomp.oacc-fortran/acc_get_property.f90
Normal file
93
libgomp/testsuite/libgomp.oacc-fortran/acc_get_property.f90
Normal file
@ -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
|
@ -1,3 +1,11 @@
|
||||
2019-12-22 Maciej W. Rozycki <macro@codesourcery.com>
|
||||
Frederik Harwath <frederik@codesourcery.com>
|
||||
Thomas Schwinge <tschwinge@codesourcery.com>
|
||||
|
||||
liboffloadmic/
|
||||
* plugin/libgomp-plugin-intelmic.cpp (GOMP_OFFLOAD_get_property):
|
||||
New function.
|
||||
|
||||
2019-10-01 Maciej W. Rozycki <macro@wdc.com>
|
||||
|
||||
* plugin/configure: Regenerate.
|
||||
|
@ -174,6 +174,27 @@ GOMP_OFFLOAD_get_num_devices (void)
|
||||
return num_devices;
|
||||
}
|
||||
|
||||
extern "C" union gomp_device_property_value
|
||||
GOMP_OFFLOAD_get_property (int n, int prop)
|
||||
{
|
||||
union gomp_device_property_value nullval = { .val = 0 };
|
||||
|
||||
if (n >= num_devices)
|
||||
{
|
||||
GOMP_PLUGIN_error
|
||||
("Request for a property of a non-existing Intel MIC device %i", n);
|
||||
return nullval;
|
||||
}
|
||||
|
||||
switch (prop)
|
||||
{
|
||||
case GOMP_DEVICE_PROPERTY_VENDOR:
|
||||
return (union gomp_device_property_value) { .ptr = "Intel" };
|
||||
default:
|
||||
return nullval;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
offload (const char *file, uint64_t line, int device, const char *name,
|
||||
int num_vars, VarDesc *vars, const void **async_data)
|
||||
|
Loading…
Reference in New Issue
Block a user