Add support for limiting number of CCS engines

This commit adds support for ZEX_NUMBER_OF_CCS flag which can be used
for limiting number of CCS engines

Format is as follows:

ZEX_NUMBER_OF_CCS=RootDeviceIndex:NumberOfCCS;RootDeviceIndex:NumberOfCCS...

i.e. setting Root Device Index 0 to 4 CCS, and Root Device Index 1 To 1 CCS

ZEX_NUMBER_OF_CCS=0:4,1:1

Related-To: NEO-7195
Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
Mateusz Jablonski
2022-07-25 12:13:27 +00:00
committed by Compute-Runtime-Automation
parent 787b71c7d0
commit 7b86c8da2e
13 changed files with 240 additions and 2 deletions

View File

@@ -12,4 +12,5 @@
DECLARE_DEBUG_VARIABLE(bool, MakeAllBuffersResident, false, "Make all buffers resident after creation") DECLARE_DEBUG_VARIABLE(bool, MakeAllBuffersResident, false, "Make all buffers resident after creation")
DECLARE_DEBUG_VARIABLE(int32_t, OverrideDefaultFP64Settings, -1, "-1: dont override, 0: disable, 1: enable.") DECLARE_DEBUG_VARIABLE(int32_t, OverrideDefaultFP64Settings, -1, "-1: dont override, 0: disable, 1: enable.")
DECLARE_DEBUG_VARIABLE(std::string, ZE_AFFINITY_MASK, std::string("default"), "Refer to the Level Zero Specification for a description") DECLARE_DEBUG_VARIABLE(std::string, ZE_AFFINITY_MASK, std::string("default"), "Refer to the Level Zero Specification for a description")
DECLARE_DEBUG_VARIABLE(std::string, ZEX_NUMBER_OF_CCS, std::string("default"), "Define number of CCS engines per root device, e.g. setting Root Device Index 0 to 4 CCS, and Root Device Index 1 To 1 CCS: ZEX_NUMBER_OF_CCS=0:4,1:1")
DECLARE_DEBUG_VARIABLE(bool, ZE_ENABLE_PCI_ID_DEVICE_ORDER, true, "Refer to the Level Zero Specification for a description") DECLARE_DEBUG_VARIABLE(bool, ZE_ENABLE_PCI_ID_DEVICE_ORDER, true, "Refer to the Level Zero Specification for a description")

View File

@@ -199,4 +199,42 @@ void ExecutionEnvironment::parseAffinityMask() {
rootDeviceEnvironments.swap(filteredEnvironments); rootDeviceEnvironments.swap(filteredEnvironments);
} }
void ExecutionEnvironment::adjustCcsCount() const {
parseCcsCountLimitations();
for (auto &rootDeviceEnvironment : rootDeviceEnvironments) {
UNRECOVERABLE_IF(!rootDeviceEnvironment);
if (!rootDeviceEnvironment->isNumberOfCcsLimited()) {
auto hwInfo = rootDeviceEnvironment->getMutableHardwareInfo();
auto hwInfoConfig = HwInfoConfig::get(hwInfo->platform.eProductFamily);
hwInfoConfig->adjustNumberOfCcs(*hwInfo);
}
}
}
void ExecutionEnvironment::parseCcsCountLimitations() const {
const auto &numberOfCcsString = DebugManager.flags.ZEX_NUMBER_OF_CCS.get();
if (numberOfCcsString.compare("default") == 0 ||
numberOfCcsString.empty()) {
return;
}
const uint32_t numRootDevices = static_cast<uint32_t>(rootDeviceEnvironments.size());
auto numberOfCcsEntries = StringHelpers::split(numberOfCcsString, ",");
for (const auto &entry : numberOfCcsEntries) {
auto subEntries = StringHelpers::split(entry, ":");
uint32_t rootDeviceIndex = StringHelpers::toUint32t(subEntries[0]);
if (rootDeviceIndex < numRootDevices) {
if (subEntries.size() > 1) {
uint32_t maxCcsCount = StringHelpers::toUint32t(subEntries[1]);
rootDeviceEnvironments[rootDeviceIndex]->limitNumberOfCcs(maxCcsCount);
}
}
}
}
} // namespace NEO } // namespace NEO

View File

@@ -27,6 +27,7 @@ class ExecutionEnvironment : public ReferenceTrackedObject<ExecutionEnvironment>
virtual void prepareRootDeviceEnvironments(uint32_t numRootDevices); virtual void prepareRootDeviceEnvironments(uint32_t numRootDevices);
void prepareRootDeviceEnvironment(const uint32_t rootDeviceIndexForReInit); void prepareRootDeviceEnvironment(const uint32_t rootDeviceIndexForReInit);
void parseAffinityMask(); void parseAffinityMask();
void adjustCcsCount() const;
void sortNeoDevices(); void sortNeoDevices();
void sortNeoDevicesDRM(); void sortNeoDevicesDRM();
void sortNeoDevicesWDDM(); void sortNeoDevicesWDDM();
@@ -44,6 +45,7 @@ class ExecutionEnvironment : public ReferenceTrackedObject<ExecutionEnvironment>
void releaseRootDeviceEnvironmentResources(RootDeviceEnvironment *rootDeviceEnvironment); void releaseRootDeviceEnvironmentResources(RootDeviceEnvironment *rootDeviceEnvironment);
protected: protected:
void parseCcsCountLimitations() const;
bool debuggingEnabled = false; bool debuggingEnabled = false;
}; };
} // namespace NEO } // namespace NEO

View File

@@ -147,4 +147,14 @@ BuiltIns *RootDeviceEnvironment::getBuiltIns() {
} }
return this->builtins.get(); return this->builtins.get();
} }
void RootDeviceEnvironment::limitNumberOfCcs(uint32_t numberOfCcs) {
hwInfo->gtSystemInfo.CCSInfo.NumberOfCCSEnabled = std::min(hwInfo->gtSystemInfo.CCSInfo.NumberOfCCSEnabled, numberOfCcs);
limitedNumberOfCcs = true;
}
bool RootDeviceEnvironment::isNumberOfCcsLimited() const {
return limitedNumberOfCcs;
}
} // namespace NEO } // namespace NEO

View File

@@ -64,6 +64,8 @@ struct RootDeviceEnvironment {
BuiltIns *getBuiltIns(); BuiltIns *getBuiltIns();
BindlessHeapsHelper *getBindlessHeapsHelper() const; BindlessHeapsHelper *getBindlessHeapsHelper() const;
void createBindlessHeapsHelper(MemoryManager *memoryManager, bool availableDevices, uint32_t rootDeviceIndex, DeviceBitfield deviceBitfield); void createBindlessHeapsHelper(MemoryManager *memoryManager, bool availableDevices, uint32_t rootDeviceIndex, DeviceBitfield deviceBitfield);
void limitNumberOfCcs(uint32_t numberOfCcs);
bool isNumberOfCcsLimited() const;
std::unique_ptr<SipKernel> sipKernels[static_cast<uint32_t>(SipKernelType::COUNT)]; std::unique_ptr<SipKernel> sipKernels[static_cast<uint32_t>(SipKernelType::COUNT)];
std::unique_ptr<GmmHelper> gmmHelper; std::unique_ptr<GmmHelper> gmmHelper;
@@ -81,6 +83,9 @@ struct RootDeviceEnvironment {
AffinityMaskHelper deviceAffinityMask{true}; AffinityMaskHelper deviceAffinityMask{true};
protected:
bool limitedNumberOfCcs = false;
private: private:
std::mutex mtx; std::mutex mtx;
}; };

View File

@@ -99,6 +99,7 @@ bool DeviceFactory::prepareDeviceEnvironmentsForProductFamilyOverride(ExecutionE
} }
executionEnvironment.parseAffinityMask(); executionEnvironment.parseAffinityMask();
executionEnvironment.adjustCcsCount();
executionEnvironment.calculateMaxOsContextCount(); executionEnvironment.calculateMaxOsContextCount();
return true; return true;
} }
@@ -158,6 +159,7 @@ bool DeviceFactory::prepareDeviceEnvironments(ExecutionEnvironment &executionEnv
executionEnvironment.sortNeoDevices(); executionEnvironment.sortNeoDevices();
executionEnvironment.parseAffinityMask(); executionEnvironment.parseAffinityMask();
executionEnvironment.adjustCcsCount();
executionEnvironment.calculateMaxOsContextCount(); executionEnvironment.calculateMaxOsContextCount();
return true; return true;

View File

@@ -132,6 +132,7 @@ class HwInfoConfig {
virtual bool isAssignEngineRoundRobinSupported() const = 0; virtual bool isAssignEngineRoundRobinSupported() const = 0;
virtual uint32_t getL1CachePolicy() const = 0; virtual uint32_t getL1CachePolicy() const = 0;
virtual bool isEvictionWhenNecessaryFlagSupported() const = 0; virtual bool isEvictionWhenNecessaryFlagSupported() const = 0;
virtual void adjustNumberOfCcs(HardwareInfo &hwInfo) const = 0;
MOCKABLE_VIRTUAL ~HwInfoConfig() = default; MOCKABLE_VIRTUAL ~HwInfoConfig() = default;
@@ -234,6 +235,7 @@ class HwInfoConfigHw : public HwInfoConfig {
bool isAssignEngineRoundRobinSupported() const override; bool isAssignEngineRoundRobinSupported() const override;
uint32_t getL1CachePolicy() const override; uint32_t getL1CachePolicy() const override;
bool isEvictionWhenNecessaryFlagSupported() const override; bool isEvictionWhenNecessaryFlagSupported() const override;
void adjustNumberOfCcs(HardwareInfo &hwInfo) const override;
protected: protected:
HwInfoConfigHw() = default; HwInfoConfigHw() = default;

View File

@@ -480,4 +480,6 @@ uint32_t HwInfoConfigHw<gfxProduct>::getL1CachePolicy() const {
return L1CachePolicyHelper<gfxProduct>::getL1CachePolicy(); return L1CachePolicyHelper<gfxProduct>::getL1CachePolicy();
} }
template <PRODUCT_FAMILY gfxProduct>
void HwInfoConfigHw<gfxProduct>::adjustNumberOfCcs(HardwareInfo &hwInfo) const {}
} // namespace NEO } // namespace NEO

View File

@@ -193,4 +193,9 @@ bool HwInfoConfigHw<gfxProduct>::isComputeDispatchAllWalkerEnableInCfeStateRequi
template <> template <>
bool HwInfoConfigHw<gfxProduct>::isIpSamplingSupported(const HardwareInfo &hwInfo) const { bool HwInfoConfigHw<gfxProduct>::isIpSamplingSupported(const HardwareInfo &hwInfo) const {
return PVC::isXt(hwInfo); return PVC::isXt(hwInfo);
}
template <>
void HwInfoConfigHw<gfxProduct>::adjustNumberOfCcs(HardwareInfo &hwInfo) const {
hwInfo.gtSystemInfo.CCSInfo.NumberOfCCSEnabled = 1;
} }

View File

@@ -10,6 +10,7 @@ AUBDumpToggleFileName = unk
OverrideGdiPath = unk OverrideGdiPath = unk
AubDumpAddMmioRegistersList = unk AubDumpAddMmioRegistersList = unk
ZE_AFFINITY_MASK = default ZE_AFFINITY_MASK = default
ZEX_NUMBER_OF_CCS = default
ZE_ENABLE_PCI_ID_DEVICE_ORDER = 1 ZE_ENABLE_PCI_ID_DEVICE_ORDER = 1
AUBDumpFilterNamedKernelStartIdx = 0 AUBDumpFilterNamedKernelStartIdx = 0
AUBDumpFilterNamedKernelEndIdx = -1 AUBDumpFilterNamedKernelEndIdx = -1
@@ -443,4 +444,4 @@ EnableBcsSwControlWa = -1
ExperimentalEnableL0DebuggerForOpenCL = 0 ExperimentalEnableL0DebuggerForOpenCL = 0
DebuggerDisableSingleAddressSbaTracking = 0 DebuggerDisableSingleAddressSbaTracking = 0
ForceImagesSupport = -1 ForceImagesSupport = -1
ForceCsrLockInBcsEnqueueOnlyForGpgpuSubmission = -1 ForceCsrLockInBcsEnqueueOnlyForGpgpuSubmission = -1

View File

@@ -6,9 +6,11 @@
*/ */
#include "shared/source/device/device.h" #include "shared/source/device/device.h"
#include "shared/source/os_interface/device_factory.h"
#include "shared/test/common/fixtures/device_fixture.h" #include "shared/test/common/fixtures/device_fixture.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h" #include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/helpers/default_hw_info.h" #include "shared/test/common/helpers/default_hw_info.h"
#include "shared/test/common/helpers/ult_hw_config.h"
#include "shared/test/common/helpers/variable_backup.h" #include "shared/test/common/helpers/variable_backup.h"
#include "shared/test/common/mocks/mock_builtins.h" #include "shared/test/common/mocks/mock_builtins.h"
#include "shared/test/common/mocks/mock_compiler_interface.h" #include "shared/test/common/mocks/mock_compiler_interface.h"
@@ -16,6 +18,7 @@
#include "shared/test/common/mocks/mock_device.h" #include "shared/test/common/mocks/mock_device.h"
#include "shared/test/common/mocks/mock_memory_manager.h" #include "shared/test/common/mocks/mock_memory_manager.h"
#include "shared/test/common/mocks/ult_device_factory.h" #include "shared/test/common/mocks/ult_device_factory.h"
#include "shared/test/common/test_macros/hw_test.h"
#include "shared/test/common/test_macros/test.h" #include "shared/test/common/test_macros/test.h"
using namespace NEO; using namespace NEO;
@@ -384,7 +387,9 @@ TEST_F(DeviceGetCapsTest, givenFlagEnabled64kbPagesWhenCallConstructorMemoryMana
EXPECT_TRUE(memoryManager->peek64kbPagesEnabled(0u)); EXPECT_TRUE(memoryManager->peek64kbPagesEnabled(0u));
} }
TEST_F(DeviceTest, givenDispatchGlobalsAllocationFailsOnSecondSubDeviceThenRtDispatchGlobalsInfoIsNull) { using DeviceTests = ::testing::Test;
TEST_F(DeviceTests, givenDispatchGlobalsAllocationFailsOnSecondSubDeviceThenRtDispatchGlobalsInfoIsNull) {
class FailMockMemoryManager : public MockMemoryManager { class FailMockMemoryManager : public MockMemoryManager {
public: public:
FailMockMemoryManager(NEO::ExecutionEnvironment &executionEnvironment) : MockMemoryManager(false, false, executionEnvironment) {} FailMockMemoryManager(NEO::ExecutionEnvironment &executionEnvironment) : MockMemoryManager(false, false, executionEnvironment) {}
@@ -412,3 +417,122 @@ TEST_F(DeviceTest, givenDispatchGlobalsAllocationFailsOnSecondSubDeviceThenRtDis
EXPECT_EQ(nullptr, rtDispatchGlobalsInfo); EXPECT_EQ(nullptr, rtDispatchGlobalsInfo);
} }
HWCMDTEST_F(IGFX_XE_HP_CORE, DeviceTests, givenZexNumberOfCssEnvVariableDefinedWhenDeviceIsCreatedThenCreateDevicesWithProperCcsCount) {
VariableBackup<UltHwConfig> backup(&ultHwConfig);
ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false;
DebugManagerStateRestore restorer;
DebugManager.flags.ZEX_NUMBER_OF_CCS.set("0:4,1:1,2:2,3:1");
DebugManager.flags.SetCommandStreamReceiver.set(1);
auto hwInfo = *defaultHwInfo;
MockExecutionEnvironment executionEnvironment(&hwInfo, false, 4);
executionEnvironment.incRefInternal();
UltDeviceFactory deviceFactory{4, 0, executionEnvironment};
{
auto device = deviceFactory.rootDevices[0];
auto computeEngineGroupIndex = device->getEngineGroupIndexFromEngineGroupType(EngineGroupType::Compute);
auto computeEngineGroup = device->getRegularEngineGroups()[computeEngineGroupIndex];
auto expectedNumberOfCcs = std::min(4u, defaultHwInfo->gtSystemInfo.CCSInfo.NumberOfCCSEnabled);
EXPECT_EQ(expectedNumberOfCcs, computeEngineGroup.engines.size());
}
{
auto device = deviceFactory.rootDevices[1];
auto computeEngineGroupIndex = device->getEngineGroupIndexFromEngineGroupType(EngineGroupType::Compute);
auto computeEngineGroup = device->getRegularEngineGroups()[computeEngineGroupIndex];
EXPECT_EQ(1u, computeEngineGroup.engines.size());
}
{
auto device = deviceFactory.rootDevices[2];
auto computeEngineGroupIndex = device->getEngineGroupIndexFromEngineGroupType(EngineGroupType::Compute);
auto computeEngineGroup = device->getRegularEngineGroups()[computeEngineGroupIndex];
auto expectedNumberOfCcs = std::min(2u, defaultHwInfo->gtSystemInfo.CCSInfo.NumberOfCCSEnabled);
EXPECT_EQ(expectedNumberOfCcs, computeEngineGroup.engines.size());
}
{
auto device = deviceFactory.rootDevices[3];
auto computeEngineGroupIndex = device->getEngineGroupIndexFromEngineGroupType(EngineGroupType::Compute);
auto computeEngineGroup = device->getRegularEngineGroups()[computeEngineGroupIndex];
EXPECT_EQ(1u, computeEngineGroup.engines.size());
}
}
HWCMDTEST_F(IGFX_XE_HP_CORE, DeviceTests, givenZexNumberOfCssAndZeAffinityMaskSetWhenDeviceIsCreatedThenProperNumberOfCcsIsExposed) {
VariableBackup<UltHwConfig> backup(&ultHwConfig);
ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false;
DebugManagerStateRestore restorer;
DebugManager.flags.CreateMultipleRootDevices.set(2);
DebugManager.flags.ZE_AFFINITY_MASK.set("1");
DebugManager.flags.ZEX_NUMBER_OF_CCS.set("0:1,1:2");
DebugManager.flags.SetCommandStreamReceiver.set(1);
auto hwInfo = *defaultHwInfo;
MockExecutionEnvironment executionEnvironment(&hwInfo, false, 2);
executionEnvironment.incRefInternal();
auto devices = DeviceFactory::createDevices(executionEnvironment);
{
auto device = devices[0].get();
EXPECT_EQ(0u, device->getRootDeviceIndex());
auto computeEngineGroupIndex = device->getEngineGroupIndexFromEngineGroupType(EngineGroupType::Compute);
auto computeEngineGroup = device->getRegularEngineGroups()[computeEngineGroupIndex];
EXPECT_EQ(1u, computeEngineGroup.engines.size());
}
}
HWCMDTEST_F(IGFX_XE_HP_CORE, DeviceTests, givenZexNumberOfCssEnvVariableIsLargerThanNumberOfAvailableCcsCountWhenDeviceIsCreatedThenCreateDevicesWithAvailableCcsCount) {
VariableBackup<UltHwConfig> backup(&ultHwConfig);
ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false;
DebugManagerStateRestore restorer;
DebugManager.flags.ZEX_NUMBER_OF_CCS.set("0:13");
DebugManager.flags.SetCommandStreamReceiver.set(1);
auto hwInfo = *defaultHwInfo;
MockExecutionEnvironment executionEnvironment(&hwInfo);
executionEnvironment.incRefInternal();
UltDeviceFactory deviceFactory{1, 0, executionEnvironment};
auto device = deviceFactory.rootDevices[0];
auto computeEngineGroupIndex = device->getEngineGroupIndexFromEngineGroupType(EngineGroupType::Compute);
auto computeEngineGroup = device->getRegularEngineGroups()[computeEngineGroupIndex];
EXPECT_EQ(defaultHwInfo->gtSystemInfo.CCSInfo.NumberOfCCSEnabled, computeEngineGroup.engines.size());
}
HWCMDTEST_F(IGFX_XE_HP_CORE, DeviceTests, givenZexNumberOfCssEnvVariableSetAmbigouslyWhenDeviceIsCreatedThenDontApplyAnyLimitations) {
VariableBackup<UltHwConfig> backup(&ultHwConfig);
ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false;
DebugManagerStateRestore restorer;
DebugManager.flags.SetCommandStreamReceiver.set(1);
for (const auto &numberOfCcsString : {"default", "", "0"}) {
DebugManager.flags.ZEX_NUMBER_OF_CCS.set(numberOfCcsString);
auto hwInfo = *defaultHwInfo;
MockExecutionEnvironment executionEnvironment(&hwInfo);
executionEnvironment.incRefInternal();
UltDeviceFactory deviceFactory{1, 0, executionEnvironment};
auto device = deviceFactory.rootDevices[0];
auto computeEngineGroupIndex = device->getEngineGroupIndexFromEngineGroupType(EngineGroupType::Compute);
auto computeEngineGroup = device->getRegularEngineGroups()[computeEngineGroupIndex];
EXPECT_EQ(defaultHwInfo->gtSystemInfo.CCSInfo.NumberOfCCSEnabled, computeEngineGroup.engines.size());
}
}

View File

@@ -8,6 +8,7 @@ if(TESTS_PVC)
set(NEO_SHARED_TESTS_PVC set(NEO_SHARED_TESTS_PVC
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_ar_tests_pvc.cpp ${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_ar_tests_pvc.cpp
${CMAKE_CURRENT_SOURCE_DIR}/device_tests_pvc.cpp
${CMAKE_CURRENT_SOURCE_DIR}/dispatch_walker_tests_pvc.cpp ${CMAKE_CURRENT_SOURCE_DIR}/dispatch_walker_tests_pvc.cpp
${CMAKE_CURRENT_SOURCE_DIR}/hw_info_tests_pvc.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hw_info_tests_pvc.cpp
${CMAKE_CURRENT_SOURCE_DIR}/product_config_helper_tests_pvc.cpp ${CMAKE_CURRENT_SOURCE_DIR}/product_config_helper_tests_pvc.cpp

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/xe_hpc_core/hw_cmds_pvc.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/helpers/default_hw_info.h"
#include "shared/test/common/helpers/ult_hw_config.h"
#include "shared/test/common/mocks/mock_device.h"
#include "shared/test/common/mocks/mock_execution_environment.h"
#include "shared/test/common/mocks/ult_device_factory.h"
#include "shared/test/common/test_macros/header/per_product_test_definitions.h"
#include "shared/test/common/test_macros/test.h"
using namespace NEO;
using DeviceTestsPvc = ::testing::Test;
HWTEST_EXCLUDE_PRODUCT(DeviceTests, givenZexNumberOfCssEnvVariableSetAmbigouslyWhenDeviceIsCreatedThenDontApplyAnyLimitations, IGFX_PVC)
PVCTEST_F(DeviceTestsPvc, WhenDeviceIsCreatedThenOnlyOneCcsEngineIsExposed) {
VariableBackup<UltHwConfig> backup(&ultHwConfig);
ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false;
DebugManagerStateRestore restorer;
DebugManager.flags.SetCommandStreamReceiver.set(1);
auto hwInfo = *defaultHwInfo;
hwInfo.featureTable.flags.ftrCCSNode = 1;
hwInfo.gtSystemInfo.CCSInfo.IsValid = 1;
hwInfo.gtSystemInfo.CCSInfo.NumberOfCCSEnabled = 4;
MockExecutionEnvironment executionEnvironment(&hwInfo);
executionEnvironment.incRefInternal();
UltDeviceFactory deviceFactory{1, 0, executionEnvironment};
auto device = deviceFactory.rootDevices[0];
auto computeEngineGroupIndex = device->getEngineGroupIndexFromEngineGroupType(EngineGroupType::Compute);
auto computeEngineGroup = device->getRegularEngineGroups()[computeEngineGroupIndex];
EXPECT_EQ(1u, computeEngineGroup.engines.size());
}