Skip to content

Commit 2762697

Browse files
Jaime ArteagaCompute-Runtime-Automation
authored andcommitted
Add support for thread arbitration policies to Level Zero
Change-Id: I6bbb2ff75dbd930b72a4f60acb0c3a9f372671cb Signed-off: Jaime Arteaga <jaime.a.arteaga.molina@intel.com>
1 parent 0bc5e15 commit 2762697

File tree

5 files changed

+338
-1
lines changed

5 files changed

+338
-1
lines changed

level_zero/core/source/cmdqueue/cmdqueue_hw.inl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "shared/source/command_container/command_encoder.h"
1313
#include "shared/source/command_stream/linear_stream.h"
1414
#include "shared/source/command_stream/preemption.h"
15+
#include "shared/source/command_stream/thread_arbitration_policy.h"
1516
#include "shared/source/device/device.h"
1617
#include "shared/source/helpers/hw_helper.h"
1718
#include "shared/source/helpers/hw_info.h"
@@ -75,6 +76,7 @@ ze_result_t CommandQueueHw<gfxCoreFamily>::executeCommandLists(
7576
size_t spaceForResidency = 0;
7677
size_t preemptionSize = 0u;
7778
size_t debuggerCmdsSize = 0;
79+
size_t threadArbitrationCmdSize = 0;
7880
constexpr size_t residencyContainerSpaceForPreemption = 2;
7981
constexpr size_t residencyContainerSpaceForFence = 1;
8082
constexpr size_t residencyContainerSpaceForTagWrite = 1;
@@ -90,6 +92,8 @@ ze_result_t CommandQueueHw<gfxCoreFamily>::executeCommandLists(
9092
statePreemption = devicePreemption;
9193
}
9294

95+
threadArbitrationCmdSize = NEO::PreambleHelper<GfxFamily>::getThreadArbitrationCommandsSize();
96+
9397
if (!commandQueueDebugCmdsProgrammed) {
9498
debuggerCmdsSize += NEO::PreambleHelper<GfxFamily>::getKernelDebuggingCommandsSize(neoDevice->isDebuggerActive());
9599
}
@@ -162,7 +166,7 @@ ze_result_t CommandQueueHw<gfxCoreFamily>::executeCommandLists(
162166
linearStreamSizeEstimate += estimateStateBaseAddressCmdSize();
163167
}
164168

165-
linearStreamSizeEstimate += preemptionSize + debuggerCmdsSize;
169+
linearStreamSizeEstimate += threadArbitrationCmdSize + preemptionSize + debuggerCmdsSize;
166170
}
167171

168172
linearStreamSizeEstimate += isCopyOnlyCommandQueue ? NEO::EncodeMiFlushDW<GfxFamily>::getMiFlushDwCmdSizeForDataWrite() : NEO::MemorySynchronizationCommands<GfxFamily>::getSizeForPipeControlWithPostSyncOperation(device->getHwInfo());
@@ -199,6 +203,13 @@ ze_result_t CommandQueueHw<gfxCoreFamily>::executeCommandLists(
199203
statePreemption = commandQueuePreemptionMode;
200204
}
201205

206+
uint32_t threadArbitrationPolicy = NEO::PreambleHelper<GfxFamily>::getDefaultThreadArbitrationPolicy();
207+
if (NEO::DebugManager.flags.OverrideThreadArbitrationPolicy.get() != -1) {
208+
threadArbitrationPolicy = static_cast<uint32_t>(NEO::DebugManager.flags.OverrideThreadArbitrationPolicy.get());
209+
}
210+
211+
NEO::PreambleHelper<GfxFamily>::programThreadArbitration(&child, threadArbitrationPolicy);
212+
202213
const bool sipKernelUsed = devicePreemption == NEO::PreemptionMode::MidThread ||
203214
neoDevice->isDebuggerActive();
204215
if (devicePreemption == NEO::PreemptionMode::MidThread) {

level_zero/core/test/unit_tests/gen11/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ if(TESTS_GEN11)
88
target_sources(${TARGET_NAME} PRIVATE
99
${COMPUTE_RUNTIME_ULT_GEN11}
1010
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
11+
${CMAKE_CURRENT_SOURCE_DIR}/test_cmdqueue_thread_arbitration_policy_gen11.cpp
1112
)
1213
endif()
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
* Copyright (C) 2020 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*
6+
*/
7+
8+
#include "shared/source/gen9/reg_configs.h"
9+
#include "shared/test/unit_test/cmd_parse/gen_cmd_parse.h"
10+
#include "shared/test/unit_test/helpers/debug_manager_state_restore.h"
11+
12+
#include "opencl/source/helpers/hardware_commands_helper.h"
13+
#include "test.h"
14+
15+
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
16+
#include "level_zero/core/test/unit_tests/mocks/mock_built_ins.h"
17+
#include "level_zero/core/test/unit_tests/mocks/mock_cmdqueue.h"
18+
19+
namespace L0 {
20+
namespace ult {
21+
22+
struct CommandQueueThreadArbitrationPolicyTests : public ::testing::Test {
23+
void SetUp() override {
24+
auto executionEnvironment = new NEO::ExecutionEnvironment();
25+
auto mockBuiltIns = new MockBuiltins();
26+
executionEnvironment->prepareRootDeviceEnvironments(1);
27+
executionEnvironment->rootDeviceEnvironments[0]->builtins.reset(mockBuiltIns);
28+
executionEnvironment->rootDeviceEnvironments[0]->setHwInfo(NEO::defaultHwInfo.get());
29+
30+
neoDevice = NEO::MockDevice::create<NEO::MockDevice>(executionEnvironment, 0u);
31+
32+
std::vector<std::unique_ptr<NEO::Device>> devices;
33+
devices.push_back(std::unique_ptr<NEO::Device>(neoDevice));
34+
35+
auto driverHandleUlt = whitebox_cast(DriverHandle::create(std::move(devices)));
36+
driverHandle.reset(driverHandleUlt);
37+
38+
ASSERT_NE(nullptr, driverHandle);
39+
40+
ze_device_handle_t hDevice;
41+
uint32_t count = 1;
42+
ze_result_t result = driverHandle->getDevice(&count, &hDevice);
43+
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
44+
device = L0::Device::fromHandle(hDevice);
45+
ASSERT_NE(nullptr, device);
46+
47+
ze_command_queue_desc_t queueDesc = {};
48+
commandQueue = whitebox_cast(CommandQueue::create(productFamily, device,
49+
neoDevice->getDefaultEngine().commandStreamReceiver,
50+
&queueDesc,
51+
false));
52+
ASSERT_NE(nullptr, commandQueue->commandStream);
53+
54+
commandList = CommandList::create(productFamily, device, false);
55+
ASSERT_NE(nullptr, commandList);
56+
}
57+
void TearDown() override {
58+
commandList->destroy();
59+
commandQueue->destroy();
60+
}
61+
62+
DebugManagerStateRestore restorer;
63+
WhiteBox<L0::CommandQueue> *commandQueue = nullptr;
64+
L0::CommandList *commandList = nullptr;
65+
std::unique_ptr<L0::ult::WhiteBox<L0::DriverHandle>> driverHandle;
66+
NEO::MockDevice *neoDevice = nullptr;
67+
L0::Device *device;
68+
};
69+
70+
HWTEST2_F(CommandQueueThreadArbitrationPolicyTests,
71+
whenCommandListIsExecutedThenDefaultRoundRobinThreadArbitrationPolicyIsUsed,
72+
IsGen11HP) {
73+
size_t usedSpaceBefore = commandQueue->commandStream->getUsed();
74+
75+
ze_command_list_handle_t hCommandList = commandList->toHandle();
76+
auto result = commandQueue->executeCommandLists(1, &hCommandList, nullptr, true);
77+
ASSERT_EQ(ZE_RESULT_SUCCESS, result);
78+
79+
size_t usedSpaceAfter = commandQueue->commandStream->getUsed();
80+
ASSERT_GT(usedSpaceAfter, usedSpaceBefore);
81+
82+
GenCmdList cmdList;
83+
ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer(
84+
cmdList, ptrOffset(commandQueue->commandStream->getCpuBase(), 0), usedSpaceAfter));
85+
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
86+
87+
auto miLoadImm = findAll<MI_LOAD_REGISTER_IMM *>(cmdList.begin(), cmdList.end());
88+
EXPECT_GE(2u, miLoadImm.size());
89+
90+
for (auto it : miLoadImm) {
91+
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*it);
92+
if (cmd->getRegisterOffset() == NEO::DebugControlReg2::address) {
93+
EXPECT_EQ(NEO::DebugControlReg2::getRegData(NEO::ThreadArbitrationPolicy::RoundRobin),
94+
cmd->getDataDword());
95+
}
96+
}
97+
}
98+
99+
HWTEST2_F(CommandQueueThreadArbitrationPolicyTests,
100+
whenCommandListIsExecutedAndOverrideThreadArbitrationPolicyDebugFlagIsSetToZeroThenAgeBasedThreadArbitrationPolicyIsUsed,
101+
IsGen11HP) {
102+
DebugManager.flags.OverrideThreadArbitrationPolicy.set(0);
103+
104+
size_t usedSpaceBefore = commandQueue->commandStream->getUsed();
105+
106+
ze_command_list_handle_t hCommandList = commandList->toHandle();
107+
auto result = commandQueue->executeCommandLists(1, &hCommandList, nullptr, true);
108+
ASSERT_EQ(ZE_RESULT_SUCCESS, result);
109+
110+
size_t usedSpaceAfter = commandQueue->commandStream->getUsed();
111+
ASSERT_GT(usedSpaceAfter, usedSpaceBefore);
112+
113+
GenCmdList cmdList;
114+
ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer(
115+
cmdList, ptrOffset(commandQueue->commandStream->getCpuBase(), 0), usedSpaceAfter));
116+
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
117+
118+
auto miLoadImm = findAll<MI_LOAD_REGISTER_IMM *>(cmdList.begin(), cmdList.end());
119+
EXPECT_GE(2u, miLoadImm.size());
120+
121+
for (auto it : miLoadImm) {
122+
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*it);
123+
if (cmd->getRegisterOffset() == NEO::DebugControlReg2::address) {
124+
EXPECT_EQ(NEO::DebugControlReg2::getRegData(NEO::ThreadArbitrationPolicy::AgeBased),
125+
cmd->getDataDword());
126+
}
127+
}
128+
}
129+
130+
HWTEST2_F(CommandQueueThreadArbitrationPolicyTests,
131+
whenCommandListIsExecutedAndOverrideThreadArbitrationPolicyDebugFlagIsSetToOneThenRoundRobinThreadArbitrationPolicyIsUsed,
132+
IsGen11HP) {
133+
DebugManager.flags.OverrideThreadArbitrationPolicy.set(1);
134+
135+
size_t usedSpaceBefore = commandQueue->commandStream->getUsed();
136+
137+
ze_command_list_handle_t hCommandList = commandList->toHandle();
138+
auto result = commandQueue->executeCommandLists(1, &hCommandList, nullptr, true);
139+
ASSERT_EQ(ZE_RESULT_SUCCESS, result);
140+
141+
size_t usedSpaceAfter = commandQueue->commandStream->getUsed();
142+
ASSERT_GT(usedSpaceAfter, usedSpaceBefore);
143+
144+
GenCmdList cmdList;
145+
ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer(
146+
cmdList, ptrOffset(commandQueue->commandStream->getCpuBase(), 0), usedSpaceAfter));
147+
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
148+
149+
auto miLoadImm = findAll<MI_LOAD_REGISTER_IMM *>(cmdList.begin(), cmdList.end());
150+
EXPECT_GE(2u, miLoadImm.size());
151+
152+
for (auto it : miLoadImm) {
153+
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*it);
154+
if (cmd->getRegisterOffset() == NEO::DebugControlReg2::address) {
155+
EXPECT_EQ(NEO::DebugControlReg2::getRegData(NEO::ThreadArbitrationPolicy::RoundRobin),
156+
cmd->getDataDword());
157+
}
158+
}
159+
}
160+
161+
} // namespace ult
162+
} // namespace L0

level_zero/core/test/unit_tests/gen9/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ if(TESTS_GEN9)
99
${COMPUTE_RUNTIME_ULT_GEN9}
1010
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
1111
${CMAKE_CURRENT_SOURCE_DIR}/test_cmdlist_append_launch_kernel_gen9.cpp
12+
${CMAKE_CURRENT_SOURCE_DIR}/test_cmdqueue_thread_arbitration_policy_gen9.cpp
1213
)
1314
endif()
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
* Copyright (C) 2020 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*
6+
*/
7+
8+
#include "shared/source/gen9/reg_configs.h"
9+
#include "shared/test/unit_test/cmd_parse/gen_cmd_parse.h"
10+
#include "shared/test/unit_test/helpers/debug_manager_state_restore.h"
11+
12+
#include "opencl/source/helpers/hardware_commands_helper.h"
13+
#include "test.h"
14+
15+
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
16+
#include "level_zero/core/test/unit_tests/mocks/mock_built_ins.h"
17+
#include "level_zero/core/test/unit_tests/mocks/mock_cmdqueue.h"
18+
19+
namespace L0 {
20+
namespace ult {
21+
22+
struct CommandQueueThreadArbitrationPolicyTests : public ::testing::Test {
23+
void SetUp() override {
24+
auto executionEnvironment = new NEO::ExecutionEnvironment();
25+
auto mockBuiltIns = new MockBuiltins();
26+
executionEnvironment->prepareRootDeviceEnvironments(1);
27+
executionEnvironment->rootDeviceEnvironments[0]->builtins.reset(mockBuiltIns);
28+
executionEnvironment->rootDeviceEnvironments[0]->setHwInfo(NEO::defaultHwInfo.get());
29+
30+
neoDevice = NEO::MockDevice::create<NEO::MockDevice>(executionEnvironment, 0u);
31+
32+
std::vector<std::unique_ptr<NEO::Device>> devices;
33+
devices.push_back(std::unique_ptr<NEO::Device>(neoDevice));
34+
35+
auto driverHandleUlt = whitebox_cast(DriverHandle::create(std::move(devices)));
36+
driverHandle.reset(driverHandleUlt);
37+
38+
ASSERT_NE(nullptr, driverHandle);
39+
40+
ze_device_handle_t hDevice;
41+
uint32_t count = 1;
42+
ze_result_t result = driverHandle->getDevice(&count, &hDevice);
43+
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
44+
device = L0::Device::fromHandle(hDevice);
45+
ASSERT_NE(nullptr, device);
46+
47+
ze_command_queue_desc_t queueDesc = {};
48+
commandQueue = whitebox_cast(CommandQueue::create(productFamily, device,
49+
neoDevice->getDefaultEngine().commandStreamReceiver,
50+
&queueDesc,
51+
false));
52+
ASSERT_NE(nullptr, commandQueue->commandStream);
53+
54+
commandList = CommandList::create(productFamily, device, false);
55+
ASSERT_NE(nullptr, commandList);
56+
}
57+
void TearDown() override {
58+
commandList->destroy();
59+
commandQueue->destroy();
60+
}
61+
62+
DebugManagerStateRestore restorer;
63+
WhiteBox<L0::CommandQueue> *commandQueue = nullptr;
64+
L0::CommandList *commandList = nullptr;
65+
std::unique_ptr<L0::ult::WhiteBox<L0::DriverHandle>> driverHandle;
66+
NEO::MockDevice *neoDevice = nullptr;
67+
L0::Device *device;
68+
};
69+
70+
HWTEST2_F(CommandQueueThreadArbitrationPolicyTests,
71+
whenCommandListIsExecutedThenDefaultRoundRobinThreadArbitrationPolicyIsUsed,
72+
IsGen9) {
73+
size_t usedSpaceBefore = commandQueue->commandStream->getUsed();
74+
75+
ze_command_list_handle_t hCommandList = commandList->toHandle();
76+
auto result = commandQueue->executeCommandLists(1, &hCommandList, nullptr, true);
77+
ASSERT_EQ(ZE_RESULT_SUCCESS, result);
78+
79+
size_t usedSpaceAfter = commandQueue->commandStream->getUsed();
80+
ASSERT_GT(usedSpaceAfter, usedSpaceBefore);
81+
82+
GenCmdList cmdList;
83+
ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer(
84+
cmdList, ptrOffset(commandQueue->commandStream->getCpuBase(), 0), usedSpaceAfter));
85+
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
86+
87+
auto miLoadImm = findAll<MI_LOAD_REGISTER_IMM *>(cmdList.begin(), cmdList.end());
88+
EXPECT_GE(2u, miLoadImm.size());
89+
90+
for (auto it : miLoadImm) {
91+
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*it);
92+
if (cmd->getRegisterOffset() == NEO::DebugControlReg2::address) {
93+
EXPECT_EQ(NEO::DebugControlReg2::getRegData(NEO::ThreadArbitrationPolicy::RoundRobin),
94+
cmd->getDataDword());
95+
}
96+
}
97+
}
98+
99+
HWTEST2_F(CommandQueueThreadArbitrationPolicyTests,
100+
whenCommandListIsExecutedAndOverrideThreadArbitrationPolicyDebugFlagIsSetToZeroThenAgeBasedThreadArbitrationPolicyIsUsed,
101+
IsGen9) {
102+
DebugManager.flags.OverrideThreadArbitrationPolicy.set(0);
103+
104+
size_t usedSpaceBefore = commandQueue->commandStream->getUsed();
105+
106+
ze_command_list_handle_t hCommandList = commandList->toHandle();
107+
auto result = commandQueue->executeCommandLists(1, &hCommandList, nullptr, true);
108+
ASSERT_EQ(ZE_RESULT_SUCCESS, result);
109+
110+
size_t usedSpaceAfter = commandQueue->commandStream->getUsed();
111+
ASSERT_GT(usedSpaceAfter, usedSpaceBefore);
112+
113+
GenCmdList cmdList;
114+
ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer(
115+
cmdList, ptrOffset(commandQueue->commandStream->getCpuBase(), 0), usedSpaceAfter));
116+
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
117+
118+
auto miLoadImm = findAll<MI_LOAD_REGISTER_IMM *>(cmdList.begin(), cmdList.end());
119+
EXPECT_GE(2u, miLoadImm.size());
120+
121+
for (auto it : miLoadImm) {
122+
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*it);
123+
if (cmd->getRegisterOffset() == NEO::DebugControlReg2::address) {
124+
EXPECT_EQ(NEO::DebugControlReg2::getRegData(NEO::ThreadArbitrationPolicy::AgeBased),
125+
cmd->getDataDword());
126+
}
127+
}
128+
}
129+
130+
HWTEST2_F(CommandQueueThreadArbitrationPolicyTests,
131+
whenCommandListIsExecutedAndOverrideThreadArbitrationPolicyDebugFlagIsSetToOneThenRoundRobinThreadArbitrationPolicyIsUsed,
132+
IsGen9) {
133+
DebugManager.flags.OverrideThreadArbitrationPolicy.set(1);
134+
135+
size_t usedSpaceBefore = commandQueue->commandStream->getUsed();
136+
137+
ze_command_list_handle_t hCommandList = commandList->toHandle();
138+
auto result = commandQueue->executeCommandLists(1, &hCommandList, nullptr, true);
139+
ASSERT_EQ(ZE_RESULT_SUCCESS, result);
140+
141+
size_t usedSpaceAfter = commandQueue->commandStream->getUsed();
142+
ASSERT_GT(usedSpaceAfter, usedSpaceBefore);
143+
144+
GenCmdList cmdList;
145+
ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer(
146+
cmdList, ptrOffset(commandQueue->commandStream->getCpuBase(), 0), usedSpaceAfter));
147+
using MI_LOAD_REGISTER_IMM = typename FamilyType::MI_LOAD_REGISTER_IMM;
148+
149+
auto miLoadImm = findAll<MI_LOAD_REGISTER_IMM *>(cmdList.begin(), cmdList.end());
150+
EXPECT_GE(2u, miLoadImm.size());
151+
152+
for (auto it : miLoadImm) {
153+
auto cmd = genCmdCast<MI_LOAD_REGISTER_IMM *>(*it);
154+
if (cmd->getRegisterOffset() == NEO::DebugControlReg2::address) {
155+
EXPECT_EQ(NEO::DebugControlReg2::getRegData(NEO::ThreadArbitrationPolicy::RoundRobin),
156+
cmd->getDataDword());
157+
}
158+
}
159+
}
160+
161+
} // namespace ult
162+
} // namespace L0

0 commit comments

Comments
 (0)