Add Subdevice support for sysman scheduler API

Change-Id: I7b2222645d93346cfd3bfd3b6561dbe21154b61f
Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
Jitendra Sharma 2020-09-23 07:08:48 +05:30 committed by sys_ocldev
parent 52b785552b
commit 77f88f9a96
15 changed files with 114 additions and 33 deletions

View File

@ -25,8 +25,8 @@ void FrequencyHandleContext::createHandle(ze_device_handle_t deviceHandle, zes_f
handleList.push_back(pFrequency);
}
ze_result_t FrequencyHandleContext::init(std::vector<ze_device_handle_t> deviceHandles) {
for (auto deviceHandle : deviceHandles) {
ze_result_t FrequencyHandleContext::init(std::vector<ze_device_handle_t> &deviceHandles) {
for (const auto &deviceHandle : deviceHandles) {
auto totalDomains = OsFrequency::getNumberOfFreqDoainsSupported(pOsSysman);
UNRECOVERABLE_IF(totalDomains > 2);
for (uint32_t frequencyDomain = 0; frequencyDomain < totalDomains; frequencyDomain++) {

View File

@ -55,7 +55,7 @@ struct FrequencyHandleContext {
FrequencyHandleContext(OsSysman *pOsSysman) : pOsSysman(pOsSysman){};
~FrequencyHandleContext();
ze_result_t init(std::vector<ze_device_handle_t> deviceHandles);
ze_result_t init(std::vector<ze_device_handle_t> &deviceHandles);
ze_result_t frequencyGet(uint32_t *pCount, zes_freq_handle_t *phFrequency);

View File

@ -20,7 +20,8 @@ const std::string LinuxSchedulerImp::defaultHeartbeatIntervalMilliSecs(".default
const std::string LinuxSchedulerImp::engineDir("engine");
ze_result_t LinuxSchedulerImp::getProperties(zes_sched_properties_t &schedProperties) {
schedProperties.onSubdevice = false;
schedProperties.onSubdevice = onSubdevice;
schedProperties.subdeviceId = subdeviceId;
schedProperties.canControl = canControlScheduler();
schedProperties.engines = this->engineType;
schedProperties.supportedModes = (1 << ZES_SCHED_MODE_TIMEOUT) | (1 << ZES_SCHED_MODE_TIMESLICE) | (1 << ZES_SCHED_MODE_EXCLUSIVE);
@ -175,9 +176,7 @@ static const std::multimap<zes_engine_type_flag_t, std::string> level0EngineType
{ZES_ENGINE_TYPE_FLAG_MEDIA, "vcs"},
{ZES_ENGINE_TYPE_FLAG_OTHER, "vecs"}};
ze_result_t OsScheduler::getNumEngineTypeAndInstances(std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines, OsSysman *pOsSysman) {
LinuxSysmanImp *pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
auto pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
static ze_result_t getNumEngineTypeAndInstancesForDevice(std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines, SysfsAccess *pSysfsAccess) {
std::vector<std::string> localListOfAllEngines = {};
auto result = pSysfsAccess->scanDirEntries(LinuxSchedulerImp::engineDir, localListOfAllEngines);
if (ZE_RESULT_SUCCESS != result) {
@ -206,15 +205,24 @@ ze_result_t OsScheduler::getNumEngineTypeAndInstances(std::map<zes_engine_type_f
return result;
}
LinuxSchedulerImp::LinuxSchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector<std::string> &listOfEngines) {
ze_result_t OsScheduler::getNumEngineTypeAndInstances(
std::map<zes_engine_type_flag_t, std::vector<std::string>> &mapOfEngines, OsSysman *pOsSysman, ze_device_handle_t subdeviceHandle) {
LinuxSysmanImp *pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
auto pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
return getNumEngineTypeAndInstancesForDevice(mapOfEngines, pSysfsAccess);
}
LinuxSchedulerImp::LinuxSchedulerImp(
OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector<std::string> &listOfEngines, ze_bool_t isSubdevice,
uint32_t subdeviceId) : engineType(type), onSubdevice(isSubdevice), subdeviceId(subdeviceId) {
LinuxSysmanImp *pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
engineType = type;
this->listOfEngines = listOfEngines;
}
OsScheduler *OsScheduler::create(OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector<std::string> &listOfEngines) {
LinuxSchedulerImp *pLinuxSchedulerImp = new LinuxSchedulerImp(pOsSysman, type, listOfEngines);
OsScheduler *OsScheduler::create(
OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector<std::string> &listOfEngines, ze_bool_t isSubdevice, uint32_t subdeviceId) {
LinuxSchedulerImp *pLinuxSchedulerImp = new LinuxSchedulerImp(pOsSysman, type, listOfEngines, isSubdevice, subdeviceId);
return static_cast<OsScheduler *>(pLinuxSchedulerImp);
}

View File

@ -6,12 +6,15 @@
*/
#pragma once
#include "shared/source/os_interface/linux/drm_neo.h"
#include "sysman/scheduler/scheduler_imp.h"
#include <string>
namespace L0 {
class SysfsAccess;
struct Device;
// Following below mappings of scheduler properties with sysfs nodes
// zes_sched_timeslice_properties_t.interval = timeslice_duration_ms
@ -28,13 +31,17 @@ class LinuxSchedulerImp : public OsScheduler, NEO::NonCopyableOrMovableClass {
ze_bool_t canControlScheduler() override;
ze_result_t getProperties(zes_sched_properties_t &properties) override;
LinuxSchedulerImp() = default;
LinuxSchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector<std::string> &listOfEngines);
LinuxSchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t type,
std::vector<std::string> &listOfEngines, ze_bool_t isSubdevice, uint32_t subdeviceId);
~LinuxSchedulerImp() override = default;
static const std::string engineDir;
protected:
SysfsAccess *pSysfsAccess = nullptr;
Device *pDevice = nullptr;
zes_engine_type_flag_t engineType = ZES_ENGINE_TYPE_FLAG_OTHER;
ze_bool_t onSubdevice = 0;
uint32_t subdeviceId = 0;
private:
static const std::string preemptTimeoutMilliSecs;

View File

@ -26,8 +26,10 @@ class OsScheduler {
virtual ze_result_t setHeartbeatInterval(uint64_t heartbeat) = 0;
virtual ze_bool_t canControlScheduler() = 0;
virtual ze_result_t getProperties(zes_sched_properties_t &properties) = 0;
static OsScheduler *create(OsSysman *pOsSysman, zes_engine_type_flag_t engineType, std::vector<std::string> &listOfEngines);
static ze_result_t getNumEngineTypeAndInstances(std::map<zes_engine_type_flag_t, std::vector<std::string>> &listOfEngines, OsSysman *pOsSysman);
static OsScheduler *create(OsSysman *pOsSysman, zes_engine_type_flag_t engineType, std::vector<std::string> &listOfEngines,
ze_bool_t isSubdevice, uint32_t subdeviceId);
static ze_result_t getNumEngineTypeAndInstances(std::map<zes_engine_type_flag_t, std::vector<std::string>> &listOfEngines,
OsSysman *pOsSysman, ze_device_handle_t subdeviceHandle);
virtual ~OsScheduler() = default;
};

View File

@ -23,16 +23,18 @@ SchedulerHandleContext::~SchedulerHandleContext() {
}
handleList.clear();
}
void SchedulerHandleContext::createHandle(zes_engine_type_flag_t engineType, std::vector<std::string> &listOfEngines) {
Scheduler *pScheduler = new SchedulerImp(pOsSysman, engineType, listOfEngines);
void SchedulerHandleContext::createHandle(zes_engine_type_flag_t engineType, std::vector<std::string> &listOfEngines, ze_device_handle_t deviceHandle) {
Scheduler *pScheduler = new SchedulerImp(pOsSysman, engineType, listOfEngines, deviceHandle);
handleList.push_back(pScheduler);
}
void SchedulerHandleContext::init() {
void SchedulerHandleContext::init(std::vector<ze_device_handle_t> &deviceHandles) {
for (const auto &deviceHandle : deviceHandles) {
std::map<zes_engine_type_flag_t, std::vector<std::string>> engineTypeInstance = {};
OsScheduler::getNumEngineTypeAndInstances(engineTypeInstance, pOsSysman);
OsScheduler::getNumEngineTypeAndInstances(engineTypeInstance, pOsSysman, deviceHandle);
for (auto itr = engineTypeInstance.begin(); itr != engineTypeInstance.end(); ++itr) {
createHandle(itr->first, itr->second);
createHandle(itr->first, itr->second, deviceHandle);
}
}
}

View File

@ -8,6 +8,7 @@
#pragma once
#include "shared/source/helpers/non_copyable_or_moveable.h"
#include "level_zero/core/source/device/device.h"
#include <level_zero/zes_api.h>
#include <map>
@ -41,7 +42,7 @@ class Scheduler : _zes_sched_handle_t {
struct SchedulerHandleContext : NEO::NonCopyableOrMovableClass {
SchedulerHandleContext(OsSysman *pOsSysman);
~SchedulerHandleContext();
void init();
void init(std::vector<ze_device_handle_t> &deviceHandles);
ze_result_t schedulerGet(uint32_t *pCount, zes_sched_handle_t *phScheduler);
OsSysman *pOsSysman = nullptr;
@ -49,7 +50,7 @@ struct SchedulerHandleContext : NEO::NonCopyableOrMovableClass {
ze_device_handle_t hCoreDevice = nullptr;
private:
void createHandle(zes_engine_type_flag_t engineType, std::vector<std::string> &listOfEngines);
void createHandle(zes_engine_type_flag_t engineType, std::vector<std::string> &listOfEngines, ze_device_handle_t deviceHandle);
};
} // namespace L0

View File

@ -143,8 +143,11 @@ void SchedulerImp::init() {
pOsScheduler->getProperties(this->properties);
}
SchedulerImp::SchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t engineType, std::vector<std::string> &listOfEngines) {
pOsScheduler = OsScheduler::create(pOsSysman, engineType, listOfEngines);
SchedulerImp::SchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t engineType, std::vector<std::string> &listOfEngines, ze_device_handle_t deviceHandle) {
ze_device_properties_t deviceProperties = {};
Device::fromHandle(deviceHandle)->getProperties(&deviceProperties);
pOsScheduler = OsScheduler::create(pOsSysman, engineType, listOfEngines,
deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, deviceProperties.subdeviceId);
UNRECOVERABLE_IF(nullptr == pOsScheduler);
init();
};

View File

@ -29,7 +29,7 @@ class SchedulerImp : public Scheduler, NEO::NonCopyableOrMovableClass {
SchedulerImp() = default;
OsScheduler *pOsScheduler = nullptr;
SchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector<std::string> &listOfEngines);
SchedulerImp(OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector<std::string> &listOfEngines, ze_device_handle_t deviceHandle);
~SchedulerImp() override;
zes_engine_type_flag_t engineType;

View File

@ -43,11 +43,12 @@ ze_result_t WddmSchedulerImp::getProperties(zes_sched_properties_t &properties)
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t OsScheduler::getNumEngineTypeAndInstances(std::map<zes_engine_type_flag_t, std::vector<std::string>> &listOfEngines, OsSysman *pOsSysman) {
ze_result_t OsScheduler::getNumEngineTypeAndInstances(std::map<zes_engine_type_flag_t, std::vector<std::string>> &listOfEngines, OsSysman *pOsSysman, ze_device_handle_t subdeviceHandle) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
OsScheduler *OsScheduler::create(OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector<std::string> &listOfEngines) {
OsScheduler *OsScheduler::create(
OsSysman *pOsSysman, zes_engine_type_flag_t type, std::vector<std::string> &listOfEngines, ze_bool_t isSubdevice, uint32_t subdeviceId) {
WddmSchedulerImp *pWddmSchedulerImp = new WddmSchedulerImp();
return static_cast<OsScheduler *>(pWddmSchedulerImp);
}

View File

@ -88,7 +88,7 @@ void SysmanDeviceImp::init() {
pEngineHandleContext->init();
}
if (pSchedulerHandleContext) {
pSchedulerHandleContext->init();
pSchedulerHandleContext->init(deviceHandles);
}
if (pRasHandleContext) {
pRasHandleContext->init();

View File

@ -366,6 +366,9 @@ void testSysmanScheduler(ze_device_handle_t &device) {
std::cout << "Could not retrieve scheduler domains" << std::endl;
return;
}
if (verbose) {
std::cout << "Number of scheduler domains = " << count << std::endl;
}
std::vector<zes_sched_handle_t> handles(count, nullptr);
VALIDATECALL(zesDeviceEnumSchedulers(device, &count, handles.data()));
@ -375,6 +378,19 @@ void testSysmanScheduler(ze_device_handle_t &device) {
if (verbose) {
std::cout << "Current Mode = " << getSchedulerModeName(currentMode) << std::endl;
}
zes_sched_properties_t schedProperties = {};
VALIDATECALL(zesSchedulerGetProperties(handle, &schedProperties));
if (verbose) {
std::cout << "Scheduler properties: onSubdevice = " << schedProperties.onSubdevice << std::endl;
if (schedProperties.onSubdevice) {
std::cout << "Scheduler properties: subdeviceId = " << schedProperties.subdeviceId << std::endl;
}
std::cout << "Scheduler properties: canControl = " << schedProperties.canControl << std::endl;
std::cout << "Scheduler properties: engines = " << schedProperties.engines << std::endl;
std::cout << "Scheduler properties: supportedModes = " << schedProperties.supportedModes << std::endl;
}
zes_sched_timeout_properties_t timeoutProperties = {};
zes_sched_timeslice_properties_t timesliceProperties = {};

View File

@ -537,5 +537,17 @@ TEST_F(SysmanDeviceFrequencyFixture, GivenValidFrequencyHandleWhenCallingzesFreq
}
}
TEST_F(SysmanMultiDeviceFixture, GivenValidDevicePointerWhenGettingFrequencyPropertiesThenValidSchedPropertiesRetrieved) {
zes_freq_properties_t properties = {};
ze_device_properties_t deviceProperties = {};
Device::fromHandle(device)->getProperties(&deviceProperties);
LinuxFrequencyImp *pLinuxFrequencyImp = new LinuxFrequencyImp(pOsSysman, deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE,
deviceProperties.subdeviceId, ZES_FREQ_DOMAIN_GPU);
EXPECT_EQ(ZE_RESULT_SUCCESS, pLinuxFrequencyImp->osFrequencyGetProperties(properties));
EXPECT_EQ(properties.subdeviceId, deviceProperties.subdeviceId);
EXPECT_EQ(properties.onSubdevice, deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE);
delete pLinuxFrequencyImp;
}
} // namespace ult
} // namespace L0

View File

@ -8,7 +8,7 @@ if(UNIX)
target_sources(${TARGET_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_scheduler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_scheduler.h
${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/test_zes_scheduler.cpp
${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/mock_sysfs_scheduler.h
)
endif()

View File

@ -34,6 +34,7 @@ class SysmanDeviceSchedulerFixture : public SysmanDeviceFixture {
protected:
std::unique_ptr<Mock<SchedulerSysfsAccess>> pSysfsAccess;
SysfsAccess *pSysfsAccessOld = nullptr;
std::vector<ze_device_handle_t> deviceHandles;
void SetUp() override {
SysmanDeviceFixture::SetUp();
@ -56,7 +57,22 @@ class SysmanDeviceSchedulerFixture : public SysmanDeviceFixture {
ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _))
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<SchedulerSysfsAccess>::getscanDirEntries));
pSysmanDeviceImp->pSchedulerHandleContext->init();
// delete handles created in initial SysmanDeviceHandleContext::init() call
for (auto handle : pSysmanDeviceImp->pSchedulerHandleContext->handleList) {
delete handle;
}
pSysmanDeviceImp->pSchedulerHandleContext->handleList.clear();
uint32_t subDeviceCount = 0;
// We received a device handle. Check for subdevices in this device
Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, nullptr);
if (subDeviceCount == 0) {
deviceHandles.resize(1, device->toHandle());
} else {
deviceHandles.resize(subDeviceCount, nullptr);
Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, deviceHandles.data());
}
pSysmanDeviceImp->pSchedulerHandleContext->init(deviceHandles);
}
void TearDown() override {
@ -98,7 +114,7 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenComponentCountZeroWhenCallingzesDevice
.WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<SchedulerSysfsAccess>::getscanDirEntriesStatusReturnError));
auto pSchedulerHandleContextTest = std::make_unique<SchedulerHandleContext>(pOsSysman);
pSchedulerHandleContextTest->init();
pSchedulerHandleContextTest->init(deviceHandles);
EXPECT_EQ(0u, static_cast<uint32_t>(pSchedulerHandleContextTest->handleList.size()));
}
@ -431,5 +447,18 @@ TEST_F(SysmanDeviceSchedulerFixture, GivenValidDeviceHandleWhenCallingzesSchedul
}
}
TEST_F(SysmanMultiDeviceFixture, GivenValidDevicePointerWhenGettingSchedPropertiesThenValidSchedPropertiesRetrieved) {
zes_sched_properties_t properties = {};
std::vector<std::string> listOfEngines;
ze_device_properties_t deviceProperties = {};
Device::fromHandle(device)->getProperties(&deviceProperties);
LinuxSchedulerImp *pLinuxSchedulerImp = new LinuxSchedulerImp(pOsSysman, ZES_ENGINE_TYPE_FLAG_COMPUTE, listOfEngines,
deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, deviceProperties.subdeviceId);
EXPECT_EQ(ZE_RESULT_SUCCESS, pLinuxSchedulerImp->getProperties(properties));
EXPECT_EQ(properties.subdeviceId, deviceProperties.subdeviceId);
EXPECT_EQ(properties.onSubdevice, deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE);
delete pLinuxSchedulerImp;
}
} // namespace ult
} // namespace L0