Update code object handling for GSL, PAL and ROCm

- Correct GSL path to report targets using the TargetID syntax.

- Correct GSL path to check compatibility of code objects when
  loading.

- Add concept of an device isa and create a registery used by ROCm,
  PAL and GSL.

- Support XNACK and SRAMECC target features consistently for PAL and ROCm.

- Correct logic for NullDevices and asserts to avoid memory coruption.

- Allow all NullDevices to be created for HIP.

- Numerous other code improvements.

Change-Id: I40abf3d2b22249c1492d1af5919665f8184f4e0e


[ROCm/clr commit: c7e8d91e14]
This commit is contained in:
Tony Tye
2021-01-10 12:17:06 +00:00
parent b43d61e48f
commit 902cf1a239
30 changed files with 1020 additions and 969 deletions
+154 -120
View File
@@ -48,6 +48,7 @@
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#ifdef ROCCLR_SUPPORT_NUMA_POLICY
#include <numaif.h>
#endif // ROCCLR_SUPPORT_NUMA_POLICY
@@ -61,9 +62,9 @@
#ifndef WITHOUT_HSA_BACKEND
namespace {
inline bool getIsaMeta(const char* targetId, amd_comgr_metadata_node_t& isaMeta) {
inline bool getIsaMeta(std::string isaName, amd_comgr_metadata_node_t& isaMeta) {
amd_comgr_status_t status;
status = amd::Comgr::get_isa_metadata(targetId, &isaMeta);
status = amd::Comgr::get_isa_metadata(isaName.c_str(), &isaMeta);
return (status == AMD_COMGR_STATUS_SUCCESS) ? true : false;
}
@@ -99,34 +100,13 @@ std::vector<AgentInfo> roc::Device::cpu_agents_;
address Device::mg_sync_ = nullptr;
static HsaDeviceId getHsaDeviceId(hsa_agent_t device, uint32_t& pci_id) {
if (HSA_STATUS_SUCCESS !=
hsa_agent_get_info(device, (hsa_agent_info_t)HSA_AMD_AGENT_INFO_CHIP_ID, &pci_id)) {
return HSA_INVALID_DEVICE_ID;
bool NullDevice::create(const amd::Isa &isa) {
if (!isa.runtimeRocSupported()) {
LogPrintfError("Offline HSA device %s is not supported", isa.targetId());
return false;
}
char agent_name[64] = {0};
if (HSA_STATUS_SUCCESS != hsa_agent_get_info(device, HSA_AGENT_INFO_NAME, agent_name)) {
return HSA_INVALID_DEVICE_ID;
}
if (::strncmp(agent_name, "gfx", 3) != 0) {
return HSA_INVALID_DEVICE_ID;
}
for (uint i = 0; i < sizeof(DeviceInfo) / sizeof(AMDDeviceInfo); ++i) {
if (::strcmp(agent_name, DeviceInfo[i].machineTargetLC_) == 0) {
return i;
}
}
return HSA_INVALID_DEVICE_ID;
}
bool NullDevice::create(const AMDDeviceInfo& deviceInfo) {
online_ = false;
deviceInfo_ = deviceInfo;
// Mark the device as GPU type
info_.type_ = CL_DEVICE_TYPE_GPU;
info_.vendorId_ = 0x1002;
@@ -134,24 +114,38 @@ bool NullDevice::create(const AMDDeviceInfo& deviceInfo) {
roc::Settings* hsaSettings = new roc::Settings();
settings_ = hsaSettings;
if (!hsaSettings ||
!hsaSettings->create(false, deviceInfo_.gfxipMajor_, deviceInfo_.gfxipMinor_)) {
LogError("Error creating settings for nullptr HSA device");
!hsaSettings->create(false, isa.versionMajor(), isa.versionMinor(),
isa.xnack() == amd::Isa::Feature::Enabled)) {
LogPrintfError("Error creating settings for offline HSA device %s", isa.targetId());
return false;
}
if (!ValidateComgr()) {
LogError("Code object manager initialization failed!");
LogPrintfError("Code object manager initialization failed for offline HSA device %s",
isa.targetId());
return false;
}
if (!amd::Device::create(isa)) {
LogPrintfError("Unable to setup offline HSA device %s", isa.targetId());
return false;
}
// Report the device name
::strncpy(info_.name_, "AMD HSA Device", sizeof(info_.name_) - 1);
::strncpy(info_.name_, isa.targetId(), sizeof(info_.name_) - 1);
info_.gfxipMajor_ = isa.versionMajor();
info_.gfxipMinor_ = isa.versionMinor();
info_.gfxipStepping_ = isa.versionStepping();
::strncpy(info_.targetId_, isa.isaName().c_str(), sizeof(info_.targetId_) - 1);
info_.extensions_ = getExtensionString();
info_.maxWorkGroupSize_ = hsaSettings->maxWorkGroupSize_;
::strncpy(info_.vendor_, "Advanced Micro Devices, Inc.", sizeof(info_.vendor_) - 1);
info_.oclcVersion_ = "OpenCL C " OPENCL_C_VERSION_STR " ";
info_.spirVersions_ = "";
::strncpy(info_.driverVersion_, "1.0 Provisional (hsa)", sizeof(info_.driverVersion_) - 1);
std::stringstream ss;
ss << AMD_BUILD_STRING " (HSA," << (settings().useLightning_ ? "LC" : "HSAIL");
ss << ") [Offline]";
::strncpy(info_.driverVersion_, ss.str().c_str(), sizeof(info_.driverVersion_) - 1);
info_.version_ = "OpenCL " OPENCL_VERSION_STR " ";
return true;
}
@@ -160,6 +154,7 @@ Device::Device(hsa_agent_t bkendDevice)
: mapCacheOps_(nullptr)
, mapCache_(nullptr)
, _bkendDevice(bkendDevice)
, pciDeviceId_(0)
, gpuvm_segment_max_alloc_(0)
, alloc_granularity_(0)
, context_(nullptr)
@@ -311,37 +306,35 @@ bool NullDevice::init() {
return false;
}
// Return without initializing offline device list
return true;
#if defined(WITH_COMPILER_LIB)
// If there is an HSA enabled device online then skip any offline device
std::vector<Device*> devices;
devices = getDevices(CL_DEVICE_TYPE_GPU, false);
// Load the offline devices
// Iterate through the set of available offline devices
for (uint id = 0; id < sizeof(DeviceInfo) / sizeof(AMDDeviceInfo); id++) {
// Create offline devices for all ISAs not already associated with an online
// device. This allows code objects to be compiled for all supported ISAs.
std::vector<Device*> devices = getDevices(CL_DEVICE_TYPE_GPU, false);
for (const amd::Isa *isa = amd::Isa::begin(); isa != amd::Isa::end(); isa++) {
if (!isa->runtimeRocSupported()) {
continue;
}
bool isOnline = false;
// Check if the particular device is online
for (unsigned int i = 0; i < devices.size(); i++) {
if (::strcmp(static_cast<NullDevice*>(devices[i])->deviceInfo_.machineTarget_,
DeviceInfo[id].machineTarget_) == 0) {
for (size_t i = 0; i < devices.size(); i++) {
if (&(devices[i]->isa()) == isa) {
isOnline = true;
break;
}
}
if (isOnline) {
continue;
}
NullDevice* nullDevice = new NullDevice();
if (!nullDevice->create(DeviceInfo[id])) {
LogError("Error creating new instance of Device.");
delete nullDevice;
std::unique_ptr<NullDevice> nullDevice(new NullDevice());
if (!nullDevice) {
LogPrintfError("Error allocating new instance of offline HSA device %s", isa->targetId());
return false;
}
nullDevice->registerDevice();
if (!nullDevice->create(*isa)) {
LogPrintfError("Skipping creating new instance of offline HSA sevice %s", isa->targetId());
continue;
}
nullDevice.release()->registerDevice();
}
#endif // defined(WITH_COMPILER_LIB)
return true;
}
@@ -516,22 +509,11 @@ bool Device::init() {
for (auto agent : gpu_agents_) {
std::unique_ptr<Device> roc_device(new Device(agent));
if (!roc_device) {
LogError("Error creating new instance of Device on then heap.");
return false;
}
uint32_t pci_id;
HsaDeviceId deviceId = getHsaDeviceId(agent, pci_id);
if (deviceId == HSA_INVALID_DEVICE_ID) {
LogPrintfError("Invalid HSA device %x", pci_id);
continue;
}
roc_device->deviceInfo_ = DeviceInfo[deviceId];
roc_device->deviceInfo_.pciDeviceId_ = pci_id;
if (!roc_device->create()) {
LogError("Error creating new instance of Device.");
continue;
@@ -585,16 +567,84 @@ void Device::tearDown() {
}
bool Device::create() {
char agent_name[64] = {0};
if (HSA_STATUS_SUCCESS != hsa_agent_get_info(_bkendDevice, HSA_AGENT_INFO_NAME, agent_name)) {
LogError("Unable to get HSA device name");
return false;
}
if (HSA_STATUS_SUCCESS !=
hsa_agent_get_info(_bkendDevice, (hsa_agent_info_t)HSA_AMD_AGENT_INFO_CHIP_ID,
&pciDeviceId_)) {
LogPrintfError("Unable to get PCI ID of HSA device %s", agent_name);
return false;
}
struct agent_isas_t {
uint count;
hsa_isa_t first_isa;
} agent_isas = {0, {0}};
if (HSA_STATUS_SUCCESS !=
hsa_agent_iterate_isas(_bkendDevice,
[](hsa_isa_t isa, void* data) {
agent_isas_t* agent_isas = static_cast<agent_isas_t*>(data);
if (agent_isas->count++ == 0) {
agent_isas->first_isa = isa;
}
return HSA_STATUS_SUCCESS;
},
&agent_isas)) {
LogPrintfError("Unable to iterate supported ISAs for HSA device %s (PCI ID %x)", agent_name,
pciDeviceId_);
return false;
}
if (agent_isas.count != 1) {
LogPrintfError("HSA device %s (PCI ID %x) has %u ISAs but can only support a single ISA",
agent_name, pciDeviceId_, agent_isas.count);
return false;
}
uint32_t isa_name_length = 0;
if (HSA_STATUS_SUCCESS !=
hsa_isa_get_info_alt(agent_isas.first_isa, (hsa_isa_info_t)HSA_ISA_INFO_NAME_LENGTH,
&isa_name_length)) {
LogPrintfError("Unable to get ISA name length for HSA device %s (PCI ID %x)", agent_name,
pciDeviceId_);
return false;
}
std::vector<char> isa_name(isa_name_length + 1, '\0');
if (HSA_STATUS_SUCCESS !=
hsa_isa_get_info_alt(agent_isas.first_isa, (hsa_isa_info_t)HSA_ISA_INFO_NAME,
isa_name.data())) {
LogPrintfError("Unable to get ISA name for HSA device %s (PCI ID %x)", agent_name,
pciDeviceId_);
return false;
}
const amd::Isa *isa = amd::Isa::findIsa(isa_name.data());
if (!isa || !isa->runtimeRocSupported()) {
LogPrintfError("Unsupported HSA device %s (PCI ID %x) for ISA %s", agent_name, pciDeviceId_,
isa_name.data());
return false;
}
if (HSA_STATUS_SUCCESS !=
hsa_agent_get_info(_bkendDevice, HSA_AGENT_INFO_PROFILE, &agent_profile_)) {
LogPrintfError("Unable to get profile for HSA device %s (PCI ID %x)", agent_name, pciDeviceId_);
return false;
}
uint32_t coop_groups = 0;
// Check cooperative groups for HIP only
if (amd::IS_HIP && (HSA_STATUS_SUCCESS !=
hsa_agent_get_info(_bkendDevice,
static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_COOPERATIVE_QUEUES), &coop_groups))) {
if (amd::IS_HIP &&
(HSA_STATUS_SUCCESS !=
hsa_agent_get_info(_bkendDevice,
static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_COOPERATIVE_QUEUES),
&coop_groups))) {
LogPrintfError(
"Unable to determine if cooperative queues are supported for HSA device %s (PCI ID %x)",
agent_name, pciDeviceId_);
return false;
}
@@ -603,17 +653,23 @@ bool Device::create() {
roc::Settings* hsaSettings = new roc::Settings();
settings_ = hsaSettings;
if (!hsaSettings ||
!hsaSettings->create((agent_profile_ == HSA_PROFILE_FULL), deviceInfo_.gfxipMajor_,
deviceInfo_.gfxipMinor_, coop_groups)) {
!hsaSettings->create((agent_profile_ == HSA_PROFILE_FULL), isa->versionMajor(),
isa->versionMinor(), isa->xnack() == amd::Isa::Feature::Enabled,
coop_groups)) {
LogPrintfError("Unable to create settings for HSA device %s (PCI ID %x)", agent_name,
pciDeviceId_);
return false;
}
if (!ValidateComgr()) {
LogError("Code object manager initialization failed!");
LogPrintfError("Code object manager initialization failed for HSA device %s (PCI ID %x)",
agent_name, pciDeviceId_);
return false;
}
if (!amd::Device::create()) {
if (!amd::Device::create(*isa)) {
LogPrintfError("Unable to setup device for HSA device %s (PCI ID %x)", agent_name,
pciDeviceId_);
return false;
}
@@ -621,6 +677,8 @@ bool Device::create() {
if (HSA_STATUS_SUCCESS !=
hsa_agent_get_info(_bkendDevice,
static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_BDFID), &hsa_bdf_id)) {
LogPrintfError("Unable to determine BFD ID for HSA device %s (PCI ID %x)", agent_name,
pciDeviceId_);
return false;
}
@@ -632,6 +690,8 @@ bool Device::create() {
if (HSA_STATUS_SUCCESS !=
hsa_agent_get_info(_bkendDevice,
static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_DOMAIN), &pci_domain_id)) {
LogPrintfError("Unable to determine domain ID for HSA device %s (PCI ID %x)", agent_name,
pciDeviceId_);
return false;
}
info_.pciDomainID = pci_domain_id;
@@ -650,7 +710,8 @@ bool Device::create() {
#endif
if (populateOCLDeviceConstants() == false) {
LogError("populateOCLDeviceConstants failed!");
LogPrintfError("populateOCLDeviceConstants failed for HSA device %s (PCI ID %x)", agent_name,
pciDeviceId_);
return false;
}
@@ -995,35 +1056,11 @@ Memory* Device::getGpuMemory(amd::Memory* mem) const {
bool Device::populateOCLDeviceConstants() {
info_.available_ = true;
hsa_isa_t isa = {0};
if (hsa_agent_get_info(_bkendDevice, HSA_AGENT_INFO_ISA, &isa) != HSA_STATUS_SUCCESS) {
return false;
}
uint32_t isaNameLength = 0;
if (hsa_isa_get_info_alt(isa, HSA_ISA_INFO_NAME_LENGTH, &isaNameLength) != HSA_STATUS_SUCCESS) {
return false;
}
if ((isaNameLength + 1) > sizeof(info_.targetId_)) {
return false;
}
if (hsa_isa_get_info_alt(isa, HSA_ISA_INFO_NAME, info_.targetId_) != HSA_STATUS_SUCCESS) {
return false;
}
info_.targetId_[isaNameLength] = '\0';
char *gfxSubString = ::strstr(info_.targetId_, "gfx");
if (nullptr == gfxSubString) {
return false;
}
::strncpy(info_.name_, gfxSubString, sizeof(info_.name_) - 1);
info_.gfxipMajor_ = deviceInfo_.gfxipMajor_;
info_.gfxipMinor_ = deviceInfo_.gfxipMinor_;
info_.gfxipStepping_ = deviceInfo_.gfxipStepping_;
::strncpy(info_.name_, isa().targetId(), sizeof(info_.name_) - 1);
info_.gfxipMajor_ = isa().versionMajor();
info_.gfxipMinor_ = isa().versionMinor();
info_.gfxipStepping_ = isa().versionStepping();
::strncpy(info_.targetId_, isa().isaName().c_str(), sizeof(info_.targetId_) - 1);
char device_name[64] = {0};
if (HSA_STATUS_SUCCESS == hsa_agent_get_info(_bkendDevice,
(hsa_agent_info_t)HSA_AMD_AGENT_INFO_PRODUCT_NAME,
@@ -1072,7 +1109,7 @@ bool Device::populateOCLDeviceConstants() {
}
//TODO: add the assert statement for Raven
if ((info_.gfxipMajor_*100 + info_.gfxipMinor_*10 + info_.gfxipStepping_) != 902) {
if (!(isa().versionMajor() == 9 && isa().versionMinor() == 0 && isa().versionStepping() == 2)) {
assert(info_.maxEngineClockFrequency_ > 0);
}
@@ -1258,7 +1295,7 @@ bool Device::populateOCLDeviceConstants() {
::strncpy(info_.driverVersion_, ss.str().c_str(), sizeof(info_.driverVersion_) - 1);
// Enable OpenCL 2.0 for Vega10+
if (deviceInfo_.gfxipMajor_ >= 9) {
if (isa().versionMajor() >= 9) {
info_.version_ = "OpenCL " /*OPENCL_VERSION_STR*/"2.0" " ";
} else {
info_.version_ = "OpenCL " /*OPENCL_VERSION_STR*/"1.2" " ";
@@ -1394,14 +1431,14 @@ bool Device::populateOCLDeviceConstants() {
}
if (amd::IS_HIP) {
// Report atomics capability based on GFX IP, control on Hawaii
if (info_.hostUnifiedMemory_ || deviceInfo_.gfxipMajor_ >= 8) {
if (info_.hostUnifiedMemory_ || isa().versionMajor() >= 8) {
info_.svmCapabilities_ |= CL_DEVICE_SVM_ATOMICS;
}
}
else if (!settings().useLightning_) {
// Report atomics capability based on GFX IP, control on Hawaii
// and Vega10.
if (info_.hostUnifiedMemory_ || (deviceInfo_.gfxipMajor_ == 8)) {
if (info_.hostUnifiedMemory_ || (isa().versionMajor() == 8)) {
info_.svmCapabilities_ |= CL_DEVICE_SVM_ATOMICS;
}
}
@@ -1409,10 +1446,10 @@ bool Device::populateOCLDeviceConstants() {
if (settings().checkExtension(ClAmdDeviceAttributeQuery)) {
info_.simdPerCU_ = settings().enableWgpMode_
? (2 * deviceInfo_.simdPerCU_)
: deviceInfo_.simdPerCU_;
info_.simdWidth_ = deviceInfo_.simdWidth_;
info_.simdInstructionWidth_ = deviceInfo_.simdInstructionWidth_;
? (2 * isa().simdPerCU())
: isa().simdPerCU();
info_.simdWidth_ = isa().simdWidth();
info_.simdInstructionWidth_ = isa().simdInstructionWidth();
if (HSA_STATUS_SUCCESS !=
hsa_agent_get_info(_bkendDevice, HSA_AGENT_INFO_WAVEFRONT_SIZE, &info_.wavefrontWidth_)) {
return false;
@@ -1454,16 +1491,16 @@ bool Device::populateOCLDeviceConstants() {
info_.l2CacheSize_ = cache_sizes[1];
info_.timeStampFrequency_ = 1000000;
info_.globalMemChannelBanks_ = 4;
info_.globalMemChannelBankWidth_ = deviceInfo_.memChannelBankWidth_;
info_.localMemSizePerCU_ = deviceInfo_.localMemSizePerCU_;
info_.localMemBanks_ = deviceInfo_.localMemBanks_;
info_.globalMemChannelBankWidth_ = isa().memChannelBankWidth();
info_.localMemSizePerCU_ = isa().localMemSizePerCU();
info_.localMemBanks_ = isa().localMemBanks();
info_.numAsyncQueues_ = kMaxAsyncQueues;
info_.numRTQueues_ = info_.numAsyncQueues_;
info_.numRTCUs_ = info_.maxComputeUnits_;
//TODO: set to true once thread trace support is available
info_.threadTraceEnable_ = false;
info_.pcieDeviceId_ = deviceInfo_.pciDeviceId_;
info_.pcieDeviceId_ = pciDeviceId_;
info_.cooperativeGroups_ = settings().enableCoopGroups_;
info_.cooperativeMultiDeviceGroups_ = settings().enableCoopMultiDeviceGroups_;
}
@@ -1481,7 +1518,7 @@ bool Device::populateOCLDeviceConstants() {
// Get Values from from Comgr
amd_comgr_metadata_node_t isaMeta;
if (getIsaMeta(info_.targetId_, isaMeta)) {
if (getIsaMeta(std::move(isa().isaName()), isaMeta)) {
std::string vgprValue;
info_.availableVGPRs_ = (getValueFromIsaMeta(isaMeta, "AddressableNumVGPRs", vgprValue))
? (atoi(vgprValue.c_str()) * info_.simdPerCU_)
@@ -1595,14 +1632,11 @@ bool Device::bindExternalDevice(uint flags, void* const gfxDevice[], void* gfxCo
return false;
}
bool match = true;
match &= info_.deviceTopology_.pcie.bus == info.pci_bus;
match &= info_.deviceTopology_.pcie.device == info.pci_device;
match &= info_.deviceTopology_.pcie.function == info.pci_function;
match &= info_.vendorId_ == info.vendor_id;
match &= deviceInfo_.pciDeviceId_ == info.device_id;
return info_.deviceTopology_.pcie.bus == info.pci_bus &&
info_.deviceTopology_.pcie.device == info.pci_device &&
info_.deviceTopology_.pcie.function == info.pci_function &&
info_.vendorId_ == info.vendor_id && pciDeviceId_ == info.device_id;
return match;
#endif
}