diff --git a/projects/clr/hipamd/src/hip_device.cpp b/projects/clr/hipamd/src/hip_device.cpp index 2869822c14..978c1812ff 100644 --- a/projects/clr/hipamd/src/hip_device.cpp +++ b/projects/clr/hipamd/src/hip_device.cpp @@ -570,6 +570,7 @@ hipError_t ihipGetDeviceProperties(hipDeviceProp_tR0600* props, int device) { deviceProps.ECCEnabled = info.errorCorrectionSupport_ ? 1 : 0; deviceProps.isLargeBar = info.largeBar_ ? 1 : 0; deviceProps.asicRevision = info.asicRevision_; + deviceProps.hasExpertSchedMode = info.hasExpertSchedMode_ ? 1 : 0; deviceProps.ipcEventSupported = 1; deviceProps.streamPrioritiesSupported = 1; deviceProps.multiGpuBoardGroupID = info.deviceTopology_.pcie.device; diff --git a/projects/clr/rocclr/device/device.hpp b/projects/clr/rocclr/device/device.hpp index 6d9a74a47e..9044c5c51c 100644 --- a/projects/clr/rocclr/device/device.hpp +++ b/projects/clr/rocclr/device/device.hpp @@ -667,6 +667,8 @@ struct Info : public amd::EmbeddedObject { size_t scratchLimitMax; //! Maximum size of scratch limit of this device memory in bytes. uint32_t numberOfXccs_; //! The number of XCC(s) on the device + + bool hasExpertSchedMode_; //! Device supports expert scheduling mode }; //! Device settings diff --git a/projects/clr/rocclr/device/rocm/rocdevice.cpp b/projects/clr/rocclr/device/rocm/rocdevice.cpp index 2c907e2f19..af3df469fe 100644 --- a/projects/clr/rocclr/device/rocm/rocdevice.cpp +++ b/projects/clr/rocclr/device/rocm/rocdevice.cpp @@ -1637,6 +1637,14 @@ bool Device::populateOCLDeviceConstants() { LogError("HSA_AMD_AGENT_INFO_PM4_EMULATION query failed."); } + info_.hasExpertSchedMode_ = false; + if (HSA_STATUS_SUCCESS != + Hsa::agent_get_info(bkendDevice_, + static_cast(HSA_AMD_AGENT_INFO_HAS_EXPERT_SCHED_MODE), + &info_.hasExpertSchedMode_)) { + LogWarning("HSA_AMD_AGENT_INFO_HAS_EXPERT_SCHED_MODE query failed."); + } + ClPrint(amd::LOG_INFO, amd::LOG_INIT, "Gfx Major/Minor/Stepping: %d/%d/%d", isa().versionMajor(), isa().versionMinor(), isa().versionStepping()); ClPrint(amd::LOG_INFO, amd::LOG_INIT, "HMM support: %d, XNACK: %d, Direct host access: %d", diff --git a/projects/hip-tests/catch/unit/device/hipGetDeviceProperties.cc b/projects/hip-tests/catch/unit/device/hipGetDeviceProperties.cc index dc01b7167e..3cb1906af2 100644 --- a/projects/hip-tests/catch/unit/device/hipGetDeviceProperties.cc +++ b/projects/hip-tests/catch/unit/device/hipGetDeviceProperties.cc @@ -339,6 +339,7 @@ TEST_CASE("Print_Out_Properties") { << properties.cooperativeMultiDeviceUnmatchedBlockDim << "\n"; std::cout << std::setw(w) << "cooperativeMultiDeviceUnmatchedSharedMem: " << properties.cooperativeMultiDeviceUnmatchedSharedMem << "\n"; + std::cout << std::setw(w) << "hasExpertSchedMode: " << properties.hasExpertSchedMode << "\n"; #endif std::flush(std::cout); } @@ -421,6 +422,32 @@ TEST_CASE("Print_Out_Properties_6.0") { std::flush(std::cout); } +#if HT_AMD +/** + * Test Description + * ------------------------ + * - Verify hasExpertSchedMode property is valid (0 or 1). + * Test source + * ------------------------ + * - unit/device/hipGetDeviceProperties.cc + * Test requirements + * ------------------------ + * - Platform specific (AMD) + * - HIP_VERSION >= 6.4 + */ +TEST_CASE("Unit_hipGetDeviceProperties_hasExpertSchedMode") { + const auto device = GENERATE(range(0, HipTest::getDeviceCount())); + + hipDeviceProp_t properties; + HIP_CHECK(hipGetDeviceProperties(&properties, device)); + + // hasExpertSchedMode should be either 0 or 1 + REQUIRE((properties.hasExpertSchedMode == 0 || properties.hasExpertSchedMode == 1)); + + INFO("Device " << device << " hasExpertSchedMode: " << properties.hasExpertSchedMode); +} +#endif + /** * End doxygen group DeviceTest. * @} diff --git a/projects/hip/include/hip/hip_runtime_api.h b/projects/hip/include/hip/hip_runtime_api.h index 5df9f4d080..7bae938c89 100644 --- a/projects/hip/include/hip/hip_runtime_api.h +++ b/projects/hip/include/hip/hip_runtime_api.h @@ -251,6 +251,7 @@ typedef struct hipDeviceProp_t { /// devices with unmatched shared memories int isLargeBar; ///< 1: if it is a large PCI bar device, else 0 int asicRevision; ///< Revision of the GPU in this device + int hasExpertSchedMode; ///< 1: device supports expert scheduling mode, else 0 } hipDeviceProp_t; /** diff --git a/projects/rocr-runtime/CMakeLists.txt b/projects/rocr-runtime/CMakeLists.txt index 44850dd7cf..56d180a025 100644 --- a/projects/rocr-runtime/CMakeLists.txt +++ b/projects/rocr-runtime/CMakeLists.txt @@ -90,7 +90,7 @@ include(utils) ## Get version strings -get_version("1.18.0") +get_version("1.19.0") if (${ROCM_PATCH_VERSION}) set(VERSION_PATCH ${ROCM_PATCH_VERSION}) endif() diff --git a/projects/rocr-runtime/libhsakmt/include/hsakmt/hsakmttypes.h b/projects/rocr-runtime/libhsakmt/include/hsakmt/hsakmttypes.h index 5516d6f7d9..4067c37e5b 100644 --- a/projects/rocr-runtime/libhsakmt/include/hsakmt/hsakmttypes.h +++ b/projects/rocr-runtime/libhsakmt/include/hsakmt/hsakmttypes.h @@ -354,6 +354,8 @@ typedef struct _HsaNodeProperties HSAuint32 LuidLowPart; // Windows Locally Unique Identifier Low 4 bytes HSAuint32 LuidHighPart; // Windows Locally Unique Identifier High 4 bytes + + HSAuint8 HasExpertSchedMode;// 1 if KFD supports expert scheduling mode } HsaNodeProperties; @@ -556,24 +558,24 @@ typedef struct _HsaMemFlags // when setting this entry to 1. Scratch allocation may fail due to limited // resources. Application code is required to work without any allocation. // Allocation fails on any node without GPU function. - unsigned int AtomicAccessFull: 1; // default = 0: If set, the memory will be allocated and mapped to allow - // atomic ops processing. On AMD APU, this will use the ATC path on system - // memory, irrespective of the NonPaged flag setting (= if NonPaged is set, - // the memory is pagelocked but mapped through IOMMUv2 instead of GPUVM). + unsigned int AtomicAccessFull: 1; // default = 0: If set, the memory will be allocated and mapped to allow + // atomic ops processing. On AMD APU, this will use the ATC path on system + // memory, irrespective of the NonPaged flag setting (= if NonPaged is set, + // the memory is pagelocked but mapped through IOMMUv2 instead of GPUVM). // All atomic ops must be supported on this memory. - unsigned int AtomicAccessPartial: 1; // default = 0: See above for AtomicAccessFull description, however - // focused on AMD discrete GPU that support PCIe atomics; the memory - // allocation is mapped to allow for PCIe atomics to operate on system - // memory, irrespective of NonPaged set or the presence of an ATC path - // in the system. The atomic operations supported are limited to SWAP, - // CompareAndSwap (CAS) and FetchAdd (this PCIe op allows both atomic - // increment and decrement via 2-complement arithmetic), which are the + unsigned int AtomicAccessPartial: 1; // default = 0: See above for AtomicAccessFull description, however + // focused on AMD discrete GPU that support PCIe atomics; the memory + // allocation is mapped to allow for PCIe atomics to operate on system + // memory, irrespective of NonPaged set or the presence of an ATC path + // in the system. The atomic operations supported are limited to SWAP, + // CompareAndSwap (CAS) and FetchAdd (this PCIe op allows both atomic + // increment and decrement via 2-complement arithmetic), which are the // only atomic ops directly supported in PCI Express. - // On AMD APU, setting this flag will allocate the same type of memory - // as AtomicAccessFull, but it will be considered compatible with + // On AMD APU, setting this flag will allocate the same type of memory + // as AtomicAccessFull, but it will be considered compatible with // discrete GPU atomic operations access. - unsigned int ExecuteAccess: 1; // default = 0: Identifies if memory is primarily used for data or accessed - // for executable code (e.g. queue memory) by the host CPU or the device. + unsigned int ExecuteAccess: 1; // default = 0: Identifies if memory is primarily used for data or accessed + // for executable code (e.g. queue memory) by the host CPU or the device. // Influences the page attribute setting within the allocation unsigned int CoarseGrain : 1; // default = 0: The memory can be accessed assuming cache // coherency maintained by link infrastructure and HSA agents. @@ -1052,7 +1054,7 @@ typedef enum _HSA_EVENTID_MEMORYFLAGS typedef struct _HsaAccessAttributeFailure { - unsigned int NotPresent : 1; // Page not present or supervisor privilege + unsigned int NotPresent : 1; // Page not present or supervisor privilege unsigned int ReadOnly : 1; // Write access to a read-only page unsigned int NoExecute : 1; // Execute access to a page marked NX unsigned int GpuAccess : 1; // Host access only diff --git a/projects/rocr-runtime/libhsakmt/src/topology.c b/projects/rocr-runtime/libhsakmt/src/topology.c index 8786000e79..582d0e35ff 100644 --- a/projects/rocr-runtime/libhsakmt/src/topology.c +++ b/projects/rocr-runtime/libhsakmt/src/topology.c @@ -1300,6 +1300,12 @@ static HSAKMT_STATUS topology_sysfs_get_node_props(uint32_t node_id, if (!props->NumXcc) props->NumXcc = 1; + /* Set HasExpertSchedMode based on KFD version and gfx major version >= 12 */ + props->HasExpertSchedMode = + ((hsakmt_kfd_version_info.KernelInterfaceMajorVersion >= 1 && + hsakmt_kfd_version_info.KernelInterfaceMinorVersion > 19) && + props->EngineId.ui32.Major >= 12) ? 1 : 0; + out: free(read_buf); fclose(fd); diff --git a/projects/rocr-runtime/libhsakmt/tests/kfdtest/src/KFDTopologyTest.cpp b/projects/rocr-runtime/libhsakmt/tests/kfdtest/src/KFDTopologyTest.cpp index 2d46b41fe6..cacf2aa1cc 100644 --- a/projects/rocr-runtime/libhsakmt/tests/kfdtest/src/KFDTopologyTest.cpp +++ b/projects/rocr-runtime/libhsakmt/tests/kfdtest/src/KFDTopologyTest.cpp @@ -95,6 +95,42 @@ TEST_F(KFDTopologyTest, GetNodePropertiesInvalidNodeNum) { TEST_END } +// Test that HasExpertSchedMode is set correctly based on KFD version and GFX version +// HasExpertSchedMode = (KFD version >= 1.20) AND (GFX major >= 12) +TEST_F(KFDTopologyTest, HasExpertSchedModeProperty) { + TEST_START(TESTPROFILE_RUNALL) + + const HsaNodeProperties *pNodeProperties; + HsaVersionInfo *versionInfo = Get_Version(); + + LOG() << "KFD Version: " << versionInfo->KernelInterfaceMajorVersion << "." + << versionInfo->KernelInterfaceMinorVersion << std::endl; + + for (unsigned node = 0; node < m_SystemProperties.NumNodes; node++) { + pNodeProperties = m_NodeInfo.GetNodeProperties(node); + if (pNodeProperties != NULL && pNodeProperties->NumFComputeCores > 0) { + // GPU nodes: HasExpertSchedMode should be 1 if both conditions are met: + // 1. KFD version >= 1.20 (KernelInterfaceMajorVersion >= 1 && KernelInterfaceMinorVersion > 19) + // 2. GFX major version >= 12 + // Otherwise, it should be 0 + bool kfdVersionCheck = (versionInfo->KernelInterfaceMajorVersion >= 1 && + versionInfo->KernelInterfaceMinorVersion > 19); + bool gfxVersionCheck = (pNodeProperties->EngineId.ui32.Major >= 12); + bool expectedValue = kfdVersionCheck && gfxVersionCheck; + + LOG() << "Node " << node + << ": GFX Major=" << pNodeProperties->EngineId.ui32.Major + << ", Expected HasExpertSchedMode=" << expectedValue + << ", Actual=" << (int)pNodeProperties->HasExpertSchedMode << std::endl; + + EXPECT_EQ(pNodeProperties->HasExpertSchedMode, expectedValue ? 1 : 0) + << "Node " << node << " HasExpertSchedMode mismatch"; + } + } + + TEST_END +} + // Test that we can get memory properties successfully per node // TODO: Check validity of values returned TEST_F(KFDTopologyTest, GetNodeMemoryProperties) { diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_gpu_agent.cpp b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_gpu_agent.cpp index 2537bb8256..bd4997e9af 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_gpu_agent.cpp +++ b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/amd_gpu_agent.cpp @@ -1717,6 +1717,9 @@ hsa_status_t GpuAgent::GetInfo(hsa_agent_info_t attribute, void* value) const { static_cast(value)->low = properties_.LuidLowPart; static_cast(value)->high = properties_.LuidHighPart; break; + case HSA_AMD_AGENT_INFO_HAS_EXPERT_SCHED_MODE: + *((bool*)value) = properties_.HasExpertSchedMode != 0; + break; default: return HSA_STATUS_ERROR_INVALID_ARGUMENT; break; diff --git a/projects/rocr-runtime/runtime/hsa-runtime/inc/hsa_ext_amd.h b/projects/rocr-runtime/runtime/hsa-runtime/inc/hsa_ext_amd.h index 8c0a64afa5..98c2d1c6dc 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/inc/hsa_ext_amd.h +++ b/projects/rocr-runtime/runtime/hsa-runtime/inc/hsa_ext_amd.h @@ -66,9 +66,10 @@ * - 1.13 - hsa_amd_pointer_info: Added new registered field to hsa_amd_pointer_info_t * - 1.14 - hsa_amd_ais_file_write, hsa_amd_ais_file_read * - 1.15 - hsa_amd_register_system_event_handler: HSA_AMD_SYSTEM_SHUTDOWN + * - 1.16 - hsa_amd_agent_info_t: HSA_AMD_AGENT_INFO_HAS_EXPERT_SCHED_MODE */ #define HSA_AMD_INTERFACE_VERSION_MAJOR 1 -#define HSA_AMD_INTERFACE_VERSION_MINOR 15 +#define HSA_AMD_INTERFACE_VERSION_MINOR 16 #ifdef __cplusplus extern "C" { @@ -715,6 +716,10 @@ typedef enum hsa_amd_agent_info_s { * valid on Windows. The type of this attribute is LUID. */ HSA_AMD_AGENT_INFO_LUID = 0xA11A, + /** + * The agent supports expert scheduling mode. The type of this attribute is bool. + */ + HSA_AMD_AGENT_INFO_HAS_EXPERT_SCHED_MODE = 0xA11B, } hsa_amd_agent_info_t; /**