From d0d5a03be74ab075994cbef02df99ad69300aac9 Mon Sep 17 00:00:00 2001 From: Mayank Raghuwanshi Date: Tue, 23 May 2023 08:05:00 +0000 Subject: [PATCH] feature: Add support for Experimental zexSysmanMemoryGetBandwidth Related-To: LOCI-3838 Signed-off-by: Mayank Raghuwanshi --- .../api/core/ze_driver_api_entrypoints.h | 4 +- .../driver_experimental/public/CMakeLists.txt | 2 + .../api/driver_experimental/public/zex_api.h | 5 +- .../public/zex_sysman_memory.cpp | 47 ++++++++++ .../public/zex_sysman_memory.h | 46 ++++++++++ level_zero/core/source/driver/driver_handle.h | 8 +- .../get_extension_function_lookup_map.cpp | 3 +- .../SYSMAN_MEMORY_BANDWIDTH.md | 71 +++++++++++++++ level_zero/sysman/source/memory/memory.h | 1 + .../sysman/source/memory/memory_imp.cpp | 4 + level_zero/sysman/source/memory/memory_imp.h | 1 + .../sysman/source/sysman_driver_handle.h | 2 +- .../source/sysman_driver_handle_imp.cpp | 11 +++ .../sysman/source/sysman_driver_handle_imp.h | 6 ++ .../sysman/memory/linux/os_memory_imp.cpp | 4 + .../sysman/memory/linux/os_memory_imp.h | 2 + .../sysman/memory/linux/os_memory_imp_dg1.cpp | 4 + .../memory/linux/os_memory_imp_prelim.cpp | 91 +++++++++++++++++++ .../memory/linux/os_memory_imp_prelim.h | 3 + .../tools/source/sysman/memory/memory.h | 1 + .../tools/source/sysman/memory/memory_imp.cpp | 4 + .../tools/source/sysman/memory/memory_imp.h | 1 + .../tools/source/sysman/memory/os_memory.h | 1 + .../sysman/memory/windows/os_memory_imp.cpp | 4 + .../sysman/memory/windows/os_memory_imp.h | 1 + .../linux/test_sysman_memory_prelim.cpp | 73 +++++++++++++++ 26 files changed, 393 insertions(+), 7 deletions(-) create mode 100644 level_zero/api/driver_experimental/public/zex_sysman_memory.cpp create mode 100644 level_zero/api/driver_experimental/public/zex_sysman_memory.h create mode 100644 level_zero/doc/experimental_extensions/SYSMAN_MEMORY_BANDWIDTH.md diff --git a/level_zero/api/core/ze_driver_api_entrypoints.h b/level_zero/api/core/ze_driver_api_entrypoints.h index 95cc606ea0..92c2c6a226 100644 --- a/level_zero/api/core/ze_driver_api_entrypoints.h +++ b/level_zero/api/core/ze_driver_api_entrypoints.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2022 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -52,7 +52,7 @@ ze_result_t zeDriverGetExtensionFunctionAddress( ze_driver_handle_t hDriver, const char *name, void **ppFunctionAddress) { - return L0::DriverHandle::fromHandle(hDriver)->getExtensionFunctionAddress(name, ppFunctionAddress); + return L0::BaseDriver::fromHandle(hDriver)->getExtensionFunctionAddress(name, ppFunctionAddress); } } // namespace L0 diff --git a/level_zero/api/driver_experimental/public/CMakeLists.txt b/level_zero/api/driver_experimental/public/CMakeLists.txt index d1c0fcadfd..0cb871ab1d 100644 --- a/level_zero/api/driver_experimental/public/CMakeLists.txt +++ b/level_zero/api/driver_experimental/public/CMakeLists.txt @@ -17,4 +17,6 @@ target_sources(${L0_STATIC_LIB_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/zex_memory.h ${CMAKE_CURRENT_SOURCE_DIR}/zex_module.cpp ${CMAKE_CURRENT_SOURCE_DIR}/zex_module.h + ${CMAKE_CURRENT_SOURCE_DIR}/zex_sysman_memory.h + ${CMAKE_CURRENT_SOURCE_DIR}/zex_sysman_memory.cpp ) diff --git a/level_zero/api/driver_experimental/public/zex_api.h b/level_zero/api/driver_experimental/public/zex_api.h index e04440db83..49164a6e52 100644 --- a/level_zero/api/driver_experimental/public/zex_api.h +++ b/level_zero/api/driver_experimental/public/zex_api.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Intel Corporation + * Copyright (C) 2022-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -13,6 +13,8 @@ // 'core' API headers #include +// 'sysman' API headers +#include // driver experimental API headers #include "level_zero/api/driver_experimental/public/zex_cmdlist.h" @@ -20,5 +22,6 @@ #include "zex_driver.h" #include "zex_memory.h" #include "zex_module.h" +#include "zex_sysman_memory.h" #endif // _ZEX_API_H diff --git a/level_zero/api/driver_experimental/public/zex_sysman_memory.cpp b/level_zero/api/driver_experimental/public/zex_sysman_memory.cpp new file mode 100644 index 0000000000..05fae212fe --- /dev/null +++ b/level_zero/api/driver_experimental/public/zex_sysman_memory.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/api/driver_experimental/public/zex_sysman_memory.h" + +#include "level_zero/api/driver_experimental/public/zex_api.h" +#include "level_zero/core/source/driver/driver.h" +#include "level_zero/core/source/driver/driver_handle.h" +#include "level_zero/sysman/source/sysman_device.h" +#include "level_zero/sysman/source/sysman_driver.h" +#include "level_zero/sysman/source/sysman_driver_handle.h" +#include "level_zero/tools/source/sysman/memory/memory.h" +#include "level_zero/tools/source/sysman/sysman.h" + +namespace L0 { + +ze_result_t ZE_APICALL +zexSysmanMemoryGetBandwidth( + zes_mem_handle_t hMemory, + uint64_t *pReadCounters, + uint64_t *pWriteCounters, + uint64_t *pMaxBandwidth, + uint64_t timeout) { + if (L0::sysmanInitFromCore) { + return L0::Memory::fromHandle(hMemory)->memoryGetBandwidthEx(pReadCounters, pWriteCounters, pMaxBandwidth, timeout); + } + return L0::Sysman::Memory::fromHandle(hMemory)->memoryGetBandwidthEx(pReadCounters, pWriteCounters, pMaxBandwidth, timeout); +} + +} // namespace L0 + +extern "C" { + +ZE_APIEXPORT ze_result_t ZE_APICALL +zexSysmanMemoryGetBandwidth( + zes_mem_handle_t hMemory, + uint64_t *pReadCounters, + uint64_t *pWriteCounters, + uint64_t *pMaxBandwidth, + uint64_t timeout) { + return L0::zexSysmanMemoryGetBandwidth(hMemory, pReadCounters, pWriteCounters, pMaxBandwidth, timeout); +} +} diff --git a/level_zero/api/driver_experimental/public/zex_sysman_memory.h b/level_zero/api/driver_experimental/public/zex_sysman_memory.h new file mode 100644 index 0000000000..f47c21ed73 --- /dev/null +++ b/level_zero/api/driver_experimental/public/zex_sysman_memory.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#ifndef _ZEX_SYSMAN_MEMORY_H +#define _ZEX_SYSMAN_MEMORY_H +#if defined(__cplusplus) +#pragma once +#endif + +#include "level_zero/api/driver_experimental/public/zex_api.h" + +namespace L0 { +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get memory bandwidth +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - ::ZE_RESULT_SUCCESS +/// - ::ZE_RESULT_ERROR_UNINITIALIZED +/// - ::ZE_RESULT_ERROR_DEVICE_LOST +/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY +/// - ::ZE_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMemory` +/// - ::ZE_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pBandwidth` +/// - ::ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to query this telemetry. +ze_result_t ZE_APICALL +zexSysmanMemoryGetBandwidth( + zes_mem_handle_t hMemory, ///<[in] Handleforthecomponent. + uint64_t *pReadCounters, ///<[out] Total bytes read from memory in duration + uint64_t *pWriteCounters, ///<[out] Total bytes written to memory in duration + uint64_t *pMaxBandwidth, ///<[out] Maximum bandwidth in units of bytes/sec + uint64_t duration ///<[in] duration in milliseconds +); + +} // namespace L0 +#endif diff --git a/level_zero/core/source/driver/driver_handle.h b/level_zero/core/source/driver/driver_handle.h index 840a3e0eb4..3dd8589989 100644 --- a/level_zero/core/source/driver/driver_handle.h +++ b/level_zero/core/source/driver/driver_handle.h @@ -28,7 +28,12 @@ namespace L0 { struct Device; struct L0EnvVariables; -struct DriverHandle : _ze_driver_handle_t { +struct BaseDriver : _ze_driver_handle_t { + virtual ze_result_t getExtensionFunctionAddress(const char *pFuncName, void **pfunc) = 0; + static BaseDriver *fromHandle(ze_driver_handle_t handle) { return static_cast(handle); } +}; + +struct DriverHandle : BaseDriver { virtual ze_result_t createContext(const ze_context_desc_t *desc, uint32_t numDevices, ze_device_handle_t *phDevices, @@ -37,7 +42,6 @@ struct DriverHandle : _ze_driver_handle_t { virtual ze_result_t getProperties(ze_driver_properties_t *properties) = 0; virtual ze_result_t getApiVersion(ze_api_version_t *version) = 0; virtual ze_result_t getIPCProperties(ze_driver_ipc_properties_t *pIPCProperties) = 0; - virtual ze_result_t getExtensionFunctionAddress(const char *pFuncName, void **pfunc) = 0; virtual ze_result_t getExtensionProperties(uint32_t *pCount, ze_driver_extension_properties_t *pExtensionProperties) = 0; diff --git a/level_zero/core/source/get_extension_function_lookup_map.cpp b/level_zero/core/source/get_extension_function_lookup_map.cpp index ade4050b07..051f04251f 100644 --- a/level_zero/core/source/get_extension_function_lookup_map.cpp +++ b/level_zero/core/source/get_extension_function_lookup_map.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2022 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -25,6 +25,7 @@ std::unordered_map getExtensionFunctionsLookupMap() { addToMap(lookupMap, zexCommandListAppendWaitOnMemory); addToMap(lookupMap, zexCommandListAppendWriteToMemory); + addToMap(lookupMap, zexSysmanMemoryGetBandwidth); #undef addToMap return lookupMap; diff --git a/level_zero/doc/experimental_extensions/SYSMAN_MEMORY_BANDWIDTH.md b/level_zero/doc/experimental_extensions/SYSMAN_MEMORY_BANDWIDTH.md new file mode 100644 index 0000000000..36846a15b2 --- /dev/null +++ b/level_zero/doc/experimental_extensions/SYSMAN_MEMORY_BANDWIDTH.md @@ -0,0 +1,71 @@ + + +# Sysman Memory Bandwidth + +* [Overview](#Overview) +* [Interfaces](#Interfaces) +* [Known Issues and Limitations](#Known-Issues-and-Limitations) + +# Overview + +`zesMemoryGetBandwidth` exposes memory read, write counters and timestamp. The expectation is these +counters are monotonically increasing and user can get bandwidth information using two snapshots of +the read and write counters taken at different instances. However, the counters could overflow +depending on underlying width of the counter presented by the hardware, and currently there is no +mechanism with which user can detect these overflows. Therefore `zexSysmanMemoryGetBandwidth` is +introduced to resolve this problem it takes care of overflow internally. +`zexSysmanMemoryGetBandwidth` takes duration as input argument and provides reads and write counter +values that elapsed in that duration. This interface blocks host thread progress for the duration +specified by the user. +To calculate the bandwidth using `zexSysmanMemoryGetBandwidth` use the formula +`Bandwidth = (Readcounters + WriteCounters) / duration` + +# Interfaces + +```cpp +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get memory bandwidth +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - ::ZE_RESULT_SUCCESS +/// - ::ZE_RESULT_ERROR_UNINITIALIZED +/// - ::ZE_RESULT_ERROR_DEVICE_LOST +/// - ::ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY +/// - ::ZE_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMemory` +/// - ::ZE_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pBandwidth` +/// - ::ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to query this telemetry. +ze_result_t ZE_APICALL +zexSysmanMemoryGetBandwidth( + zes_mem_handle_t hMemory, ///<[in] Handleforthecomponent. + uint64_t *pReadCounters, ///<[out] Total bytes read from memory in duration + uint64_t *pWriteCounters, ///<[out] Total bytes written to memory in duration + uint64_t *pMaxBandwidth, ///<[out] Maximum bandwidth in units of bytes/sec + uint64_t duration ///<[in] duration in milliseconds +); +``` + +```cpp +typedef ze_result_t (*pFnzexSysmanMemoryGetBandwidth)(zes_mem_handle_t, uint64 *, uint64 *, uint64 *, uint64); +... + +pFnzexSysmanMemoryGetBandwidth zexSysmanMemoryGetBandwidth = nullptr; +ze_result_t res = zeDriverGetExtensionFunctionAddress(hDriver, "zexSysmanMemoryGetBandwidth", reinterpret_cast(&zexSysmanMemoryGetBandwidth))); +``` + +# Known Issues and Limitations + +* Implemented and validation only on Xe HPC (PVC). \ No newline at end of file diff --git a/level_zero/sysman/source/memory/memory.h b/level_zero/sysman/source/memory/memory.h index 646624e040..88cfb7ae3f 100644 --- a/level_zero/sysman/source/memory/memory.h +++ b/level_zero/sysman/source/memory/memory.h @@ -23,6 +23,7 @@ class Memory : _zes_mem_handle_t { virtual ze_result_t memoryGetProperties(zes_mem_properties_t *pProperties) = 0; virtual ze_result_t memoryGetBandwidth(zes_mem_bandwidth_t *pBandwidth) = 0; virtual ze_result_t memoryGetState(zes_mem_state_t *pState) = 0; + virtual ze_result_t memoryGetBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) = 0; static Memory *fromHandle(zes_mem_handle_t handle) { return static_cast(handle); diff --git a/level_zero/sysman/source/memory/memory_imp.cpp b/level_zero/sysman/source/memory/memory_imp.cpp index f998f15a1d..b57ef6253c 100644 --- a/level_zero/sysman/source/memory/memory_imp.cpp +++ b/level_zero/sysman/source/memory/memory_imp.cpp @@ -23,6 +23,10 @@ ze_result_t MemoryImp::memoryGetProperties(zes_mem_properties_t *pProperties) { return ZE_RESULT_SUCCESS; } +ze_result_t MemoryImp::memoryGetBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + void MemoryImp::init() { this->initSuccess = pOsMemory->isMemoryModuleSupported(); if (this->initSuccess == true) { diff --git a/level_zero/sysman/source/memory/memory_imp.h b/level_zero/sysman/source/memory/memory_imp.h index 562b5e4fdd..a0aa4ffb65 100644 --- a/level_zero/sysman/source/memory/memory_imp.h +++ b/level_zero/sysman/source/memory/memory_imp.h @@ -20,6 +20,7 @@ class MemoryImp : public Memory, NEO::NonCopyableOrMovableClass { ze_result_t memoryGetProperties(zes_mem_properties_t *pProperties) override; ze_result_t memoryGetBandwidth(zes_mem_bandwidth_t *pBandwidth) override; ze_result_t memoryGetState(zes_mem_state_t *pState) override; + ze_result_t memoryGetBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) override; MemoryImp(OsSysman *pOsSysman, bool onSubdevice, uint32_t subDeviceId); ~MemoryImp() override; diff --git a/level_zero/sysman/source/sysman_driver_handle.h b/level_zero/sysman/source/sysman_driver_handle.h index 119afae745..d8eee7fa84 100644 --- a/level_zero/sysman/source/sysman_driver_handle.h +++ b/level_zero/sysman/source/sysman_driver_handle.h @@ -15,7 +15,7 @@ namespace L0 { namespace Sysman { -struct SysmanDriverHandle : _ze_driver_handle_t { +struct SysmanDriverHandle : BaseDriver { static SysmanDriverHandle *fromHandle(zes_driver_handle_t handle) { return static_cast(handle); } inline zes_driver_handle_t toHandle() { return this; } diff --git a/level_zero/sysman/source/sysman_driver_handle_imp.cpp b/level_zero/sysman/source/sysman_driver_handle_imp.cpp index 4605331d44..e9f1fff158 100644 --- a/level_zero/sysman/source/sysman_driver_handle_imp.cpp +++ b/level_zero/sysman/source/sysman_driver_handle_imp.cpp @@ -13,6 +13,7 @@ #include "shared/source/helpers/hw_info.h" #include "shared/source/os_interface/os_interface.h" +#include "level_zero/core/source/get_extension_function_lookup_map.h" #include "level_zero/sysman/source/sysman_device.h" #include "level_zero/sysman/source/sysman_driver.h" @@ -44,6 +45,15 @@ ze_result_t SysmanDriverHandleImp::initialize(NEO::ExecutionEnvironment &executi return ZE_RESULT_SUCCESS; } +ze_result_t SysmanDriverHandleImp::getExtensionFunctionAddress(const char *pFuncName, void **pfunc) { + auto funcAddr = extensionFunctionsLookupMap.find(std::string(pFuncName)); + if (funcAddr != extensionFunctionsLookupMap.end()) { + *pfunc = funcAddr->second; + return ZE_RESULT_SUCCESS; + } + return ZE_RESULT_ERROR_INVALID_ARGUMENT; +} + SysmanDriverHandle *SysmanDriverHandle::create(NEO::ExecutionEnvironment &executionEnvironment, ze_result_t *returnValue) { SysmanDriverHandleImp *driverHandle = new SysmanDriverHandleImp; UNRECOVERABLE_IF(nullptr == driverHandle); @@ -56,6 +66,7 @@ SysmanDriverHandle *SysmanDriverHandle::create(NEO::ExecutionEnvironment &execut return nullptr; } + driverHandle->extensionFunctionsLookupMap = getExtensionFunctionsLookupMap(); GlobalSysmanDriver = driverHandle; *returnValue = res; return driverHandle; diff --git a/level_zero/sysman/source/sysman_driver_handle_imp.h b/level_zero/sysman/source/sysman_driver_handle_imp.h index 0749c4123b..3f155bfce6 100644 --- a/level_zero/sysman/source/sysman_driver_handle_imp.h +++ b/level_zero/sysman/source/sysman_driver_handle_imp.h @@ -8,6 +8,9 @@ #pragma once #include "level_zero/sysman/source/sysman_driver_handle.h" +#include +#include + namespace L0 { namespace Sysman { struct SysmanDevice; @@ -18,6 +21,9 @@ struct SysmanDriverHandleImp : SysmanDriverHandle { ze_result_t getDevice(uint32_t *pCount, zes_device_handle_t *phDevices) override; std::vector sysmanDevices; uint32_t numDevices = 0; + + ze_result_t getExtensionFunctionAddress(const char *pFuncName, void **pfunc) override; + std::unordered_map extensionFunctionsLookupMap; }; extern struct SysmanDriverHandleImp *GlobalSysmanDriver; diff --git a/level_zero/tools/source/sysman/memory/linux/os_memory_imp.cpp b/level_zero/tools/source/sysman/memory/linux/os_memory_imp.cpp index 5e63be429b..18137528b1 100644 --- a/level_zero/tools/source/sysman/memory/linux/os_memory_imp.cpp +++ b/level_zero/tools/source/sysman/memory/linux/os_memory_imp.cpp @@ -41,6 +41,10 @@ ze_result_t LinuxMemoryImp::getState(zes_mem_state_t *pState) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } +ze_result_t LinuxMemoryImp::getBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + std::unique_ptr OsMemory::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) { std::unique_ptr pLinuxMemoryImp = std::make_unique(pOsSysman, onSubdevice, subdeviceId); return pLinuxMemoryImp; diff --git a/level_zero/tools/source/sysman/memory/linux/os_memory_imp.h b/level_zero/tools/source/sysman/memory/linux/os_memory_imp.h index a4fdaa8788..b42fd89936 100644 --- a/level_zero/tools/source/sysman/memory/linux/os_memory_imp.h +++ b/level_zero/tools/source/sysman/memory/linux/os_memory_imp.h @@ -21,6 +21,8 @@ class LinuxMemoryImp : public OsMemory, NEO::NonCopyableOrMovableClass { ze_result_t getProperties(zes_mem_properties_t *pProperties) override; ze_result_t getBandwidth(zes_mem_bandwidth_t *pBandwidth) override; ze_result_t getState(zes_mem_state_t *pState) override; + ze_result_t getBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) override; + bool isMemoryModuleSupported() override; LinuxMemoryImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); LinuxMemoryImp() = default; diff --git a/level_zero/tools/source/sysman/memory/linux/os_memory_imp_dg1.cpp b/level_zero/tools/source/sysman/memory/linux/os_memory_imp_dg1.cpp index 55da3914d3..59546e34b8 100644 --- a/level_zero/tools/source/sysman/memory/linux/os_memory_imp_dg1.cpp +++ b/level_zero/tools/source/sysman/memory/linux/os_memory_imp_dg1.cpp @@ -41,6 +41,10 @@ ze_result_t LinuxMemoryImp::getBandwidth(zes_mem_bandwidth_t *pBandwidth) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } +ze_result_t LinuxMemoryImp::getBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + ze_result_t LinuxMemoryImp::getState(zes_mem_state_t *pState) { std::vector deviceRegions; if (pDrm->queryMemoryInfo() == false) { diff --git a/level_zero/tools/source/sysman/memory/linux/os_memory_imp_prelim.cpp b/level_zero/tools/source/sysman/memory/linux/os_memory_imp_prelim.cpp index f612b0bffa..96b58621d7 100644 --- a/level_zero/tools/source/sysman/memory/linux/os_memory_imp_prelim.cpp +++ b/level_zero/tools/source/sysman/memory/linux/os_memory_imp_prelim.cpp @@ -293,6 +293,97 @@ ze_result_t LinuxMemoryImp::getBandwidth(zes_mem_bandwidth_t *pBandwidth) { return result; } +uint64_t getCounterIncrement(uint32_t counterMaxValue, uint64_t prevValue, uint64_t currentValue) { + if (currentValue < prevValue) { + return (counterMaxValue - prevValue + currentValue); + } + return (currentValue - prevValue); +} +ze_result_t LinuxMemoryImp::getHbmBandwidthEx(uint32_t numHbmModules, uint32_t counterMaxValue, uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) { + std::vector prevReadCounters(numHbmModules, 0); + std::vector prevWriteCounters(numHbmModules, 0); + uint64_t totalReadCounters = 0; + uint64_t totalWriteCounters = 0; + bool counterInit = false; + ze_result_t result = ZE_RESULT_ERROR_UNKNOWN; + std::string vfId = ""; + result = getVFIDString(vfId); + if (result != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s():getVFIDString returning error:0x%x while retriving VFID string \n", __FUNCTION__, result); + return result; + } + auto &hwInfo = pDevice->getNEODevice()->getHardwareInfo(); + auto productFamily = hwInfo.platform.eProductFamily; + auto &productHelper = pDevice->getNEODevice()->getProductHelper(); + auto stepping = productHelper.getSteppingFromHwRevId(hwInfo); + auto timeToExitLoop = std::chrono::steady_clock::now() + std::chrono::duration(timeout); + do { + for (auto hbmModuleIndex = 0u; hbmModuleIndex < numHbmModules; hbmModuleIndex++) { + uint32_t counterValue = 0; + // To read counters from VFID 0 and HBM module 0, key would be: VF0_HBM0_READ + std::string readCounterKey = vfId + "_HBM" + std::to_string(hbmModuleIndex) + "_READ"; + result = pPmt->readValue(readCounterKey, counterValue); + if (result != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s():readValue for readCounterKey returning error:0x%x \n", __FUNCTION__, result); + return result; + } + if (counterInit) { + totalReadCounters += getCounterIncrement(counterMaxValue, prevReadCounters[hbmModuleIndex], counterValue); + } + prevReadCounters[hbmModuleIndex] = counterValue; + counterValue = 0; + // To write counters to VFID 0 and HBM module 0, key would be: VF0_HBM0_Write + std::string writeCounterKey = vfId + "_HBM" + std::to_string(hbmModuleIndex) + "_WRITE"; + result = pPmt->readValue(writeCounterKey, counterValue); + if (result != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s():readValue for writeCounterKey returning error:0x%x \n", __FUNCTION__, result); + return result; + } + if (counterInit) { + totalWriteCounters += getCounterIncrement(counterMaxValue, prevWriteCounters[hbmModuleIndex], counterValue); + } + prevWriteCounters[hbmModuleIndex] = counterValue; + } + counterInit = true; + } while (std::chrono::steady_clock::now() <= timeToExitLoop); + + constexpr uint64_t transactionSize = 32; + *pReadCounters = (totalReadCounters * transactionSize); + *pWriteCounters = (totalWriteCounters * transactionSize); + uint64_t hbmFrequency = 0; + getHbmFrequency(productFamily, stepping, hbmFrequency); + + *pMaxBandwidth = memoryBusWidth * hbmFrequency * numHbmModules; // Value in bytes/secs + return result; +} + +ze_result_t LinuxMemoryImp::getBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBw, uint64_t timeout) { + if (pPmt == nullptr) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + ze_result_t result = ZE_RESULT_ERROR_UNKNOWN; + auto &hwInfo = pDevice->getNEODevice()->getHardwareInfo(); + auto productFamily = hwInfo.platform.eProductFamily; + uint32_t numHbmModules = 0u; + uint32_t counterMaxValue; + switch (productFamily) { + case IGFX_XE_HP_SDV: + numHbmModules = 2u; + counterMaxValue = UINT32_MAX; + result = getHbmBandwidthEx(numHbmModules, counterMaxValue, pReadCounters, pWriteCounters, pMaxBw, timeout); + break; + case IGFX_PVC: + numHbmModules = 4u; + counterMaxValue = UINT32_MAX; + result = getHbmBandwidthEx(numHbmModules, counterMaxValue, pReadCounters, pWriteCounters, pMaxBw, timeout); + break; + default: + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + break; + } + return result; +} + ze_result_t LinuxMemoryImp::getState(zes_mem_state_t *pState) { pState->health = ZES_MEM_HEALTH_UNKNOWN; FirmwareUtil *pFwInterface = pLinuxSysmanImp->getFwUtilInterface(); diff --git a/level_zero/tools/source/sysman/memory/linux/os_memory_imp_prelim.h b/level_zero/tools/source/sysman/memory/linux/os_memory_imp_prelim.h index 726699fd9d..1ce4dd2781 100644 --- a/level_zero/tools/source/sysman/memory/linux/os_memory_imp_prelim.h +++ b/level_zero/tools/source/sysman/memory/linux/os_memory_imp_prelim.h @@ -24,6 +24,8 @@ class LinuxMemoryImp : public OsMemory, NEO::NonCopyableOrMovableClass { ze_result_t getProperties(zes_mem_properties_t *pProperties) override; ze_result_t getBandwidth(zes_mem_bandwidth_t *pBandwidth) override; ze_result_t getState(zes_mem_state_t *pState) override; + ze_result_t getBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) override; + bool isMemoryModuleSupported() override; LinuxMemoryImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); LinuxMemoryImp() = default; @@ -42,6 +44,7 @@ class LinuxMemoryImp : public OsMemory, NEO::NonCopyableOrMovableClass { ze_result_t getVFIDString(std::string &vfID); ze_result_t getBandwidthForDg2(zes_mem_bandwidth_t *pBandwidth); ze_result_t getHbmBandwidth(uint32_t numHbmModules, zes_mem_bandwidth_t *pBandwidth); + ze_result_t getHbmBandwidthEx(uint32_t numHbmModules, uint32_t counterMaxValue, uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout); static const std::string deviceMemoryHealth; bool isSubdevice = false; uint32_t subdeviceId = 0; diff --git a/level_zero/tools/source/sysman/memory/memory.h b/level_zero/tools/source/sysman/memory/memory.h index c0e6017f03..4b853534a2 100644 --- a/level_zero/tools/source/sysman/memory/memory.h +++ b/level_zero/tools/source/sysman/memory/memory.h @@ -22,6 +22,7 @@ class Memory : _zes_mem_handle_t { virtual ze_result_t memoryGetProperties(zes_mem_properties_t *pProperties) = 0; virtual ze_result_t memoryGetBandwidth(zes_mem_bandwidth_t *pBandwidth) = 0; virtual ze_result_t memoryGetState(zes_mem_state_t *pState) = 0; + virtual ze_result_t memoryGetBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) = 0; static Memory *fromHandle(zes_mem_handle_t handle) { return static_cast(handle); diff --git a/level_zero/tools/source/sysman/memory/memory_imp.cpp b/level_zero/tools/source/sysman/memory/memory_imp.cpp index 00da5229f1..aac027c46d 100644 --- a/level_zero/tools/source/sysman/memory/memory_imp.cpp +++ b/level_zero/tools/source/sysman/memory/memory_imp.cpp @@ -24,6 +24,10 @@ ze_result_t MemoryImp::memoryGetProperties(zes_mem_properties_t *pProperties) { return ZE_RESULT_SUCCESS; } +ze_result_t MemoryImp::memoryGetBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) { + return pOsMemory->getBandwidthEx(pReadCounters, pWriteCounters, pMaxBandwidth, timeout); +} + void MemoryImp::init() { this->initSuccess = pOsMemory->isMemoryModuleSupported(); if (this->initSuccess == true) { diff --git a/level_zero/tools/source/sysman/memory/memory_imp.h b/level_zero/tools/source/sysman/memory/memory_imp.h index f529366198..1ab4739be7 100644 --- a/level_zero/tools/source/sysman/memory/memory_imp.h +++ b/level_zero/tools/source/sysman/memory/memory_imp.h @@ -19,6 +19,7 @@ class MemoryImp : public Memory, NEO::NonCopyableOrMovableClass { ze_result_t memoryGetProperties(zes_mem_properties_t *pProperties) override; ze_result_t memoryGetBandwidth(zes_mem_bandwidth_t *pBandwidth) override; ze_result_t memoryGetState(zes_mem_state_t *pState) override; + ze_result_t memoryGetBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) override; MemoryImp(OsSysman *pOsSysman, ze_device_handle_t handle); ~MemoryImp() override; diff --git a/level_zero/tools/source/sysman/memory/os_memory.h b/level_zero/tools/source/sysman/memory/os_memory.h index 35cb01956f..d72b589f99 100644 --- a/level_zero/tools/source/sysman/memory/os_memory.h +++ b/level_zero/tools/source/sysman/memory/os_memory.h @@ -19,6 +19,7 @@ class OsMemory { virtual ze_result_t getProperties(zes_mem_properties_t *pProperties) = 0; virtual ze_result_t getBandwidth(zes_mem_bandwidth_t *pBandwidth) = 0; virtual ze_result_t getState(zes_mem_state_t *pState) = 0; + virtual ze_result_t getBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) = 0; virtual bool isMemoryModuleSupported() = 0; static std::unique_ptr create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); virtual ~OsMemory() {} diff --git a/level_zero/tools/source/sysman/memory/windows/os_memory_imp.cpp b/level_zero/tools/source/sysman/memory/windows/os_memory_imp.cpp index d50e1e0307..1f9700b877 100644 --- a/level_zero/tools/source/sysman/memory/windows/os_memory_imp.cpp +++ b/level_zero/tools/source/sysman/memory/windows/os_memory_imp.cpp @@ -168,6 +168,10 @@ ze_result_t WddmMemoryImp::getProperties(zes_mem_properties_t *pProperties) { return ZE_RESULT_SUCCESS; } +ze_result_t WddmMemoryImp::getBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + ze_result_t WddmMemoryImp::getBandwidth(zes_mem_bandwidth_t *pBandwidth) { uint32_t valueSmall = 0; uint64_t valueLarge = 0; diff --git a/level_zero/tools/source/sysman/memory/windows/os_memory_imp.h b/level_zero/tools/source/sysman/memory/windows/os_memory_imp.h index a00972d861..2584902e28 100644 --- a/level_zero/tools/source/sysman/memory/windows/os_memory_imp.h +++ b/level_zero/tools/source/sysman/memory/windows/os_memory_imp.h @@ -28,6 +28,7 @@ class WddmMemoryImp : public OsMemory, NEO::NonCopyableOrMovableClass { ze_result_t getProperties(zes_mem_properties_t *pProperties) override; ze_result_t getBandwidth(zes_mem_bandwidth_t *pBandwidth) override; ze_result_t getState(zes_mem_state_t *pState) override; + ze_result_t getBandwidthEx(uint64_t *pReadCounters, uint64_t *pWriteCounters, uint64_t *pMaxBandwidth, uint64_t timeout) override; bool isMemoryModuleSupported() override; WddmMemoryImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); WddmMemoryImp() = default; diff --git a/level_zero/tools/test/unit_tests/sources/sysman/memory/linux/test_sysman_memory_prelim.cpp b/level_zero/tools/test/unit_tests/sources/sysman/memory/linux/test_sysman_memory_prelim.cpp index 5200cd6601..981bd24f95 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/memory/linux/test_sysman_memory_prelim.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/memory/linux/test_sysman_memory_prelim.cpp @@ -458,6 +458,79 @@ HWTEST2_F(SysmanDeviceMemoryFixture, GivenValidMemoryHandleWhenCallingzesSysmanM } } +HWTEST2_F(SysmanDeviceMemoryFixture, GivenValidMemoryHandleWhenCallingGetBandwidthExWhenVFID1IsActiveThenSuccessIsReturnedAndBandwidthIsValid, IsPVC) { + setLocalSupportedAndReinit(true); + auto hwInfo = pLinuxSysmanImp->getDeviceHandle()->getNEODevice()->getRootDeviceEnvironment().getMutableHardwareInfo(); + auto &productHelper = pLinuxSysmanImp->getDeviceHandle()->getNEODevice()->getProductHelper(); + hwInfo->platform.usRevId = productHelper.getHwRevIdFromStepping(REVISION_B, *hwInfo); + auto pPmt = static_cast(pLinuxSysmanImp->getPlatformMonitoringTechAccess(0)); + + pPmt->mockVfid1Status = true; + pSysfsAccess->mockReadUInt64Value.push_back(hbmRP0Frequency); + pSysfsAccess->mockReadReturnStatus.push_back(ZE_RESULT_SUCCESS); + uint64_t readCounters = 0; + uint64_t writeCounters = 0; + uint64_t maxBandwidth = 0; + uint64_t timeout = 1; + std::unique_ptr pLinuxMemoryImp = std::make_unique(pOsSysman, true, 0); + EXPECT_EQ(pLinuxMemoryImp->getBandwidthEx(&readCounters, &writeCounters, &maxBandwidth, timeout), ZE_RESULT_SUCCESS); + EXPECT_EQ(readCounters, 0u); + EXPECT_EQ(writeCounters, 0u); + uint64_t expectedBandwidth = 128 * hbmRP0Frequency * 1000 * 1000 * 4; + EXPECT_EQ(maxBandwidth, expectedBandwidth); +} + +HWTEST2_F(SysmanDeviceMemoryFixture, GivenValidMemoryHandleWhenCallingGetBandwidthExWhenVFID0IsActiveThenSuccessIsReturnedAndBandwidthIsValid, IsPVC) { + setLocalSupportedAndReinit(true); + auto hwInfo = pLinuxSysmanImp->getDeviceHandle()->getNEODevice()->getRootDeviceEnvironment().getMutableHardwareInfo(); + auto &productHelper = pLinuxSysmanImp->getDeviceHandle()->getNEODevice()->getProductHelper(); + hwInfo->platform.usRevId = productHelper.getHwRevIdFromStepping(REVISION_B, *hwInfo); + auto pPmt = static_cast(pLinuxSysmanImp->getPlatformMonitoringTechAccess(0)); + + pPmt->mockVfid0Status = true; + pSysfsAccess->mockReadUInt64Value.push_back(hbmRP0Frequency); + pSysfsAccess->mockReadReturnStatus.push_back(ZE_RESULT_SUCCESS); + uint64_t readCounters = 0; + uint64_t writeCounters = 0; + uint64_t maxBandwidth = 0; + uint64_t timeout = 1; + std::unique_ptr pLinuxMemoryImp = std::make_unique(pOsSysman, true, 0); + EXPECT_EQ(pLinuxMemoryImp->getBandwidthEx(&readCounters, &writeCounters, &maxBandwidth, timeout), ZE_RESULT_SUCCESS); + EXPECT_EQ(readCounters, 0u); + EXPECT_EQ(writeCounters, 0u); + uint64_t expectedBandwidth = 128 * hbmRP0Frequency * 1000 * 1000 * 4; + EXPECT_EQ(maxBandwidth, expectedBandwidth); +} + +TEST_F(SysmanDeviceMemoryFixture, GivenValidMemoryHandleWhenCallingGetBandwidthExForUnknownPlatformThenFailureIsReturned) { + setLocalSupportedAndReinit(true); + auto hwInfo = *NEO::defaultHwInfo.get(); + hwInfo.platform.eProductFamily = IGFX_UNKNOWN; + pLinuxSysmanImp->getDeviceHandle()->getNEODevice()->getRootDeviceEnvironmentRef().setHwInfoAndInitHelpers(&hwInfo); + uint64_t readCounters = 0; + uint64_t writeCounters = 0; + uint64_t maxBandwidth = 0; + uint64_t timeout = 1; + std::unique_ptr pLinuxMemoryImp = std::make_unique(pOsSysman, true, 0); + EXPECT_EQ(pLinuxMemoryImp->getBandwidthEx(&readCounters, &writeCounters, &maxBandwidth, timeout), ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); +} + +TEST_F(SysmanDeviceMemoryFixture, GivenValidMemoryHandleWhenCallingGetMemoryGetBandwidthExWhenPmtObjectIsNullThenFailureRetuned) { + for (auto &subDeviceIdToPmtEntry : pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject) { + if (subDeviceIdToPmtEntry.second != nullptr) { + delete subDeviceIdToPmtEntry.second; + subDeviceIdToPmtEntry.second = nullptr; + } + } + setLocalSupportedAndReinit(true); + uint64_t readCounters = 0; + uint64_t writeCounters = 0; + uint64_t maxBandwidth = 0; + uint64_t timeout = 1; + std::unique_ptr pLinuxMemoryImp = std::make_unique(pOsSysman, true, 0); + EXPECT_EQ(pLinuxMemoryImp->getBandwidthEx(&readCounters, &writeCounters, &maxBandwidth, timeout), ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); +} + HWTEST2_F(SysmanDeviceMemoryFixture, GivenValidUsRevIdForRevisionBWhenCallingzesSysmanMemoryGetBandwidthThenSuccessIsReturnedAndBandwidthIsValid, IsPVC) { setLocalSupportedAndReinit(true); auto handles = getMemoryHandles(memoryHandleComponentCount);