Add OpenACC acc_get_property support for AMD GCN

Add full support for the OpenACC 2.6 acc_get_property and
acc_get_property_string functions to the libgomp GCN plugin.

libgomp/
	* plugin-gcn.c (struct agent_info): Add fields "name" and
	"vendor_name" ...
	(GOMP_OFFLOAD_init_device): ... and init from here.
	(struct hsa_context_info): Add field "driver_version_s" ...
	(init_hsa_contest): ... and init from here.
	(GOMP_OFFLOAD_openacc_get_property): Replace stub with a proper
	implementation.
	* testsuite/libgomp.oacc-c-c++-common/acc_get_property.c:
	Enable test execution for amdgcn and host offloading targets.
	* testsuite/libgomp.oacc-fortran/acc_get_property.f90: Likewise.
	* testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c
	(expect_device_properties): Split function into ...
	(expect_device_string_properties): ... this new function ...
	(expect_device_memory): ... and this new function.
	* testsuite/libgomp.oacc-c-c++-common/acc_get_property-gcn.c:
	Add test.
This commit is contained in:
Frederik Harwath 2020-01-29 10:19:50 +01:00
parent f57ccb55cd
commit 2e5ea57959
6 changed files with 266 additions and 49 deletions

View File

@ -1,3 +1,23 @@
2020-01-29 Frederik Harwath <frederik@codesourcery.com>
* plugin-gcn.c (struct agent_info): Add fields "name" and
"vendor_name" ...
(GOMP_OFFLOAD_init_device): ... and init from here.
(struct hsa_context_info): Add field "driver_version_s" ...
(init_hsa_contest): ... and init from here.
(GOMP_OFFLOAD_openacc_get_property): Replace stub with a proper
implementation.
* testsuite/libgomp.oacc-c-c++-common/acc_get_property.c:
Enable test execution for amdgcn and host offloading targets.
* testsuite/libgomp.oacc-fortran/acc_get_property.f90: Likewise.
* testsuite/libgomp.oacc-c-c++-common/acc_get_property-aux.c
(expect_device_properties): Split function into ...
(expect_device_string_properties): ... this new function ...
(expect_device_memory): ... and this new function.
* testsuite/libgomp.oacc-c-c++-common/acc_get_property-gcn.c:
Add test.
2020-01-28 Julian Brown <julian@codesourcery.com>
* testsuite/libgomp.oacc-fortran/deep-copy-2.f90: Remove test from here.

View File

@ -425,7 +425,10 @@ struct agent_info
/* The instruction set architecture of the device. */
gcn_isa device_isa;
/* Name of the agent. */
char name[64];
/* Name of the vendor of the agent. */
char vendor_name[64];
/* Command queues of the agent. */
hsa_queue_t *sync_queue;
struct goacc_asyncqueue *async_queues, *omp_async_queue;
@ -544,6 +547,8 @@ struct hsa_context_info
int agent_count;
/* Array of agent_info structures describing the individual HSA agents. */
struct agent_info *agents;
/* Driver version string. */
char driver_version_s[30];
};
/* Format of the on-device heap.
@ -1513,6 +1518,25 @@ init_hsa_context (void)
GOMP_PLUGIN_error ("Failed to list all HSA runtime agents");
}
uint16_t minor, major;
status = hsa_fns.hsa_system_get_info_fn (HSA_SYSTEM_INFO_VERSION_MINOR,
&minor);
if (status != HSA_STATUS_SUCCESS)
GOMP_PLUGIN_error ("Failed to obtain HSA runtime minor version");
status = hsa_fns.hsa_system_get_info_fn (HSA_SYSTEM_INFO_VERSION_MAJOR,
&major);
if (status != HSA_STATUS_SUCCESS)
GOMP_PLUGIN_error ("Failed to obtain HSA runtime major version");
size_t len = sizeof hsa_context.driver_version_s;
int printed = snprintf (hsa_context.driver_version_s, len,
"HSA Runtime %hu.%hu", (unsigned short int)major,
(unsigned short int)minor);
if (printed >= len)
GCN_WARNING ("HSA runtime version string was truncated."
"Version %hu.%hu is too long.", (unsigned short int)major,
(unsigned short int)minor);
hsa_context.initialized = true;
return true;
}
@ -3410,15 +3434,19 @@ GOMP_OFFLOAD_init_device (int n)
return hsa_error ("Error requesting maximum queue size of the GCN agent",
status);
char buf[64];
status = hsa_fns.hsa_agent_get_info_fn (agent->id, HSA_AGENT_INFO_NAME,
&buf);
&agent->name);
if (status != HSA_STATUS_SUCCESS)
return hsa_error ("Error querying the name of the agent", status);
agent->device_isa = isa_code (buf);
agent->device_isa = isa_code (agent->name);
if (agent->device_isa < 0)
return hsa_error ("Unknown GCN agent architecture.", HSA_STATUS_ERROR);
return hsa_error ("Unknown GCN agent architecture", HSA_STATUS_ERROR);
status = hsa_fns.hsa_agent_get_info_fn (agent->id, HSA_AGENT_INFO_VENDOR_NAME,
&agent->vendor_name);
if (status != HSA_STATUS_SUCCESS)
return hsa_error ("Error querying the vendor name of the agent", status);
status = hsa_fns.hsa_queue_create_fn (agent->id, queue_size,
HSA_QUEUE_TYPE_MULTI,
@ -4115,12 +4143,37 @@ GOMP_OFFLOAD_openacc_async_dev2host (int device, void *dst, const void *src,
union goacc_property_value
GOMP_OFFLOAD_openacc_get_property (int device, enum goacc_property prop)
{
/* Stub. Check device and return default value for unsupported properties. */
/* TODO: Implement this function. */
get_agent_info (device);
struct agent_info *agent = get_agent_info (device);
union goacc_property_value nullval = { .val = 0 };
return nullval;
union goacc_property_value propval = { .val = 0 };
switch (prop)
{
case GOACC_PROPERTY_FREE_MEMORY:
/* Not supported. */
break;
case GOACC_PROPERTY_MEMORY:
{
size_t size;
hsa_region_t region = agent->data_region;
hsa_status_t status =
hsa_fns.hsa_region_get_info_fn (region, HSA_REGION_INFO_SIZE, &size);
if (status == HSA_STATUS_SUCCESS)
propval.val = size;
break;
}
case GOACC_PROPERTY_NAME:
propval.ptr = agent->name;
break;
case GOACC_PROPERTY_VENDOR:
propval.ptr = agent->vendor_name;
break;
case GOACC_PROPERTY_DRIVER:
propval.ptr = hsa_context.driver_version_s;
break;
}
return propval;
}
/* Set up plugin-specific thread-local-data (host-side). */

View File

@ -6,39 +6,20 @@
#include <stdio.h>
#include <string.h>
void expect_device_properties
(acc_device_t dev_type, int dev_num,
size_t expected_memory, const char* expected_vendor,
const char* expected_name, const char* expected_driver)
void expect_device_string_properties (acc_device_t dev_type, int dev_num,
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 ();
}
size_t total_mem = acc_get_property (dev_num, dev_type,
acc_property_memory);
if (total_mem != expected_memory)
{
fprintf (stderr, "Expected acc_property_memory to equal %zu, "
"but was %zu.\n", expected_memory, total_mem);
abort ();
}
size_t free_mem = acc_get_property (dev_num, dev_type,
acc_property_free_memory);
if (free_mem > total_mem)
{
fprintf (stderr, "Expected acc_property_free_memory <= acc_property_memory"
", but free memory was %zu and total memory was %zu.\n",
free_mem, total_mem);
abort ();
}
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 ();
}
const char *name = acc_get_property_string (dev_num, dev_type,
acc_property_name);
@ -75,6 +56,40 @@ void expect_device_properties
"but was %s.\n", s);
abort ();
}
}
void expect_device_memory (acc_device_t dev_type, int dev_num,
size_t expected_total_memory)
{
size_t total_mem = acc_get_property (dev_num, dev_type,
acc_property_memory);
if (total_mem != expected_total_memory)
{
fprintf (stderr, "Expected acc_property_memory to equal %zu, "
"but was %zu.\n", expected_total_memory, total_mem);
abort ();
}
size_t free_mem = acc_get_property (dev_num, dev_type,
acc_property_free_memory);
if (free_mem > total_mem)
{
fprintf (stderr, "Expected acc_property_free_memory <= acc_property_memory"
", but free memory was %zu and total memory was %zu.\n",
free_mem, total_mem);
abort ();
}
}
void expect_device_properties (acc_device_t dev_type, int dev_num,
size_t expected_total_memory,
const char* expected_vendor,
const char* expected_name,
const char* expected_driver)
{
expect_device_string_properties (dev_type, dev_num, expected_vendor,
expected_name, expected_driver);
expect_device_memory (dev_type, dev_num, expected_total_memory);
}

View File

@ -0,0 +1,132 @@
/* Test the `acc_get_property' and `acc_get_property_string' library
functions on amdgcn devices by comparing property values with
those obtained through the HSA API. */
/* { dg-additional-sources acc_get_property-aux.c } */
/* { dg-additional-options "-ldl" } */
/* { dg-do run { target openacc_amdgcn_accel_selected } } */
#include <dlfcn.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openacc.h>
#ifndef __cplusplus
typedef int bool;
#endif
#include <hsa.h>
void expect_device_string_properties (acc_device_t dev_type, int dev_num,
const char* expected_vendor,
const char* expected_name,
const char* expected_driver);
hsa_status_t (*hsa_agent_get_info_fn) (hsa_agent_t agent,
hsa_agent_info_t attribute,
void *value);
hsa_status_t (*hsa_system_get_info_fn) (hsa_system_info_t attribute,
void *value);
hsa_status_t (*hsa_iterate_agents_fn)
(hsa_status_t (*callback)(hsa_agent_t agent, void *data), void *data);
hsa_status_t (*hsa_init_fn) (void);
char* support_cpu_devices;
void test_setup ()
{
char* env_runtime;
char* hsa_runtime_lib;
void *handle;
#define DLSYM_FN(function) \
function##_fn = (typeof(function##_fn))dlsym (handle, #function); \
if (function##_fn == NULL) \
{ \
fprintf (stderr, "Could not get symbol " #function ".\n"); \
abort (); \
}
env_runtime = getenv ("HSA_RUNTIME_LIB");
hsa_runtime_lib = env_runtime ? env_runtime : (char*)"libhsa-runtime64.so";
handle = dlopen (hsa_runtime_lib, RTLD_LAZY);
if (!handle)
{
fprintf (stderr, "Could not load %s.\n", hsa_runtime_lib);
abort ();
}
DLSYM_FN (hsa_agent_get_info)
DLSYM_FN (hsa_system_get_info)
DLSYM_FN (hsa_iterate_agents)
DLSYM_FN (hsa_init)
hsa_init_fn ();
support_cpu_devices = getenv ("GCN_SUPPORT_CPU_DEVICES");
}
static hsa_status_t check_agent_properties (hsa_agent_t agent, void *dev_num_arg)
{
char name[64];
char vendor_name[64];
uint16_t minor;
uint16_t major;
char driver[60];
hsa_status_t status;
hsa_device_type_t device_type;
int* dev_num = (int*)dev_num_arg;
#define AGENT_GET_INFO(info_type, val) \
status = hsa_agent_get_info_fn (agent, info_type, &val); \
if (status != HSA_STATUS_SUCCESS) \
{ \
fprintf (stderr, "Failed to obtain " #info_type ".\n"); \
abort (); \
}
#define SYSTEM_GET_INFO(info_type, val) \
status = hsa_system_get_info_fn (info_type, &val); \
if (status != HSA_STATUS_SUCCESS) \
{ \
fprintf (stderr, "Failed to obtain " #info_type ".\n"); \
abort (); \
}
AGENT_GET_INFO (HSA_AGENT_INFO_DEVICE, device_type)
/* Skip unsupported device types. Mimic the GCN plugin's behavior. */
if (!(device_type == HSA_DEVICE_TYPE_GPU
|| (support_cpu_devices && device_type == HSA_DEVICE_TYPE_CPU)))
return HSA_STATUS_SUCCESS;
AGENT_GET_INFO (HSA_AGENT_INFO_NAME, name)
AGENT_GET_INFO (HSA_AGENT_INFO_VENDOR_NAME, vendor_name)
SYSTEM_GET_INFO (HSA_SYSTEM_INFO_VERSION_MINOR, minor)
SYSTEM_GET_INFO (HSA_SYSTEM_INFO_VERSION_MAJOR, major)
snprintf (driver, sizeof driver, "HSA Runtime %hu.%hu",
(unsigned short int)major, (unsigned short int)minor);
expect_device_string_properties(acc_device_radeon, *dev_num,
vendor_name, name, driver);
(*dev_num)++;
return status;
}
int main ()
{
int dev_num = 0;
test_setup ();
hsa_status_t status =
hsa_iterate_agents_fn (&check_agent_properties, &dev_num);
return status;
}

View File

@ -3,8 +3,7 @@
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. */
/* { dg-do run } */
#include <openacc.h>
#include <stdlib.h>
@ -20,7 +19,7 @@ print_device_properties(acc_device_t type)
const char *s;
size_t v;
int dev_count = acc_get_num_devices(type);
int dev_count = acc_get_num_devices (type);
for (int i = 0; i < dev_count; ++i)
{

View File

@ -3,8 +3,6 @@
! 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