Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[L0] Enable Copy engine support with in-order command lists #2636

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Prev Previous commit
Next Next commit
Apply review comments
  • Loading branch information
konradkusiak97 committed Feb 24, 2025
commit 8f49c1d2860d3b830b9362a9f05ce9a8a183a31a
70 changes: 32 additions & 38 deletions source/adapters/level_zero/command_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ ur_result_t getEventsFromSyncPoints(
* command list (copy or compute), to indicate when it's finished executing.
* @param[in] CommandType The type of the command.
* @param[in] CommandBuffer The CommandBuffer where the command is appended.
* @param[in] isFirstNode A boolean inidicating if the current node is at the
* @param[in] IsFirstNode A boolean inidicating if the current node is at the
* beginning of the command list.
* @param[in] isCopy A boolean indicating if the current command uses copy
* engine.
Expand All @@ -185,14 +185,14 @@ ur_result_t getEventsFromSyncPoints(
*/
ur_result_t createSyncPointBetweenCopyAndCompute(
ur_command_t CommandType, ur_exp_command_buffer_handle_t CommandBuffer,
bool isFirstNode, bool isCopy,
bool IsFirstNode, bool IsCopy,
ze_event_handle_t &ZeSignalPrevCommandEvent) {
if (isFirstNode) {
CommandBuffer->MCopyCommandListEmpty = !isCopy;
CommandBuffer->MComputeCommandListEmpty = isCopy;
CommandBuffer->WasPrevCopyCommandList = isCopy;
if (IsFirstNode) {
CommandBuffer->MCopyCommandListEmpty = !IsCopy;
CommandBuffer->MComputeCommandListEmpty = IsCopy;
CommandBuffer->MWasPrevCopyCommandList = IsCopy;
return UR_RESULT_SUCCESS;
} else if (CommandBuffer->WasPrevCopyCommandList == isCopy) {
} else if (CommandBuffer->MWasPrevCopyCommandList == IsCopy) {
return UR_RESULT_SUCCESS;
}

Expand All @@ -210,14 +210,14 @@ ur_result_t createSyncPointBetweenCopyAndCompute(
* finished executing.
*/
ZeSignalPrevCommandEvent = SignalPrevCommandEvent->ZeEvent;
if (CommandBuffer->WasPrevCopyCommandList && !isCopy) {
if (CommandBuffer->MWasPrevCopyCommandList && !IsCopy) {
ZE2UR_CALL(zeCommandListAppendSignalEvent,
(CommandBuffer->ZeCopyCommandList, ZeSignalPrevCommandEvent));
CommandBuffer->WasPrevCopyCommandList = false;
CommandBuffer->MWasPrevCopyCommandList = false;
} else {
ZE2UR_CALL(zeCommandListAppendSignalEvent,
(CommandBuffer->ZeComputeCommandList, ZeSignalPrevCommandEvent));
CommandBuffer->WasPrevCopyCommandList = true;
CommandBuffer->MWasPrevCopyCommandList = true;
}

// Get sync point and register the event with it.
Expand Down Expand Up @@ -283,7 +283,7 @@ ur_result_t createSyncPointAndGetZeEvents(
return UR_RESULT_SUCCESS;
}

// Shared by all memory read/write/copy PI interfaces.
// Shared by all memory read/write/copy UR interfaces.
// Helper function for common code when enqueuing memory operations to a command
// buffer.
ur_result_t enqueueCommandBufferMemCopyHelper(
Expand All @@ -300,9 +300,9 @@ ur_result_t enqueueCommandBufferMemCopyHelper(
false, RetSyncPoint, ZeEventList, ZeLaunchEvent));

// The chooseCommandList() will modify MComputeCommandListEmpty and
// MCopyCommandListEmpty so isFirstNode needs to be created before that.
bool isFirstNode{CommandBuffer->MComputeCommandListEmpty &&
CommandBuffer->MCopyCommandListEmpty};
// MCopyCommandListEmpty so isFirstNode needs to be called beforehand.
bool IsFirstNode{CommandBuffer->isFirstNode()};

ze_command_list_handle_t ZeCommandList =
CommandBuffer->chooseCommandList(PreferCopyEngine);

Expand All @@ -312,7 +312,7 @@ ur_result_t enqueueCommandBufferMemCopyHelper(
ZeCommandList == CommandBuffer->ZeCopyCommandList) {
ze_event_handle_t ZeSignalPrevCommandEvent = nullptr;
UR_CALL(createSyncPointBetweenCopyAndCompute(CommandType, CommandBuffer,
isFirstNode, true /*isCopy=*/,
IsFirstNode, true /*isCopy=*/,
ZeSignalPrevCommandEvent));
if (ZeSignalPrevCommandEvent) {
ZeEventList.push_back(ZeSignalPrevCommandEvent);
Expand Down Expand Up @@ -374,9 +374,9 @@ ur_result_t enqueueCommandBufferMemCopyRectHelper(
false, RetSyncPoint, ZeEventList, ZeLaunchEvent));

// The chooseCommandList() will modify MComputeCommandListEmpty and
// MCopyCommandListEmpty so isFirstNode needs to be created before that.
bool isFirstNode{CommandBuffer->MComputeCommandListEmpty &&
CommandBuffer->MCopyCommandListEmpty};
// MCopyCommandListEmpty so isFirstNode needs to be called beforehand.
bool IsFirstNode{CommandBuffer->isFirstNode()};

ze_command_list_handle_t ZeCommandList =
CommandBuffer->chooseCommandList(PreferCopyEngine);

Expand All @@ -386,7 +386,7 @@ ur_result_t enqueueCommandBufferMemCopyRectHelper(
ZeCommandList == CommandBuffer->ZeCopyCommandList) {
ze_event_handle_t ZeSignalPrevCommandEvent = nullptr;
UR_CALL(createSyncPointBetweenCopyAndCompute(CommandType, CommandBuffer,
isFirstNode, true /*isCopy=*/,
IsFirstNode, true /*isCopy=*/,
ZeSignalPrevCommandEvent));
if (ZeSignalPrevCommandEvent) {
ZeEventList.push_back(ZeSignalPrevCommandEvent);
Expand Down Expand Up @@ -423,9 +423,9 @@ ur_result_t enqueueCommandBufferFillHelper(
preferCopyEngineForFill(CommandBuffer, PatternSize, PreferCopyEngine));

// The chooseCommandList() will modify MComputeCommandListEmpty and
// MCopyCommandListEmpty so isFirstNode needs to be created before that.
bool isFirstNode{CommandBuffer->MComputeCommandListEmpty &&
CommandBuffer->MCopyCommandListEmpty};
// MCopyCommandListEmpty so isFirstNode needs to be called beforehand.
bool IsFirstNode{CommandBuffer->isFirstNode()};

ze_command_list_handle_t ZeCommandList =
CommandBuffer->chooseCommandList(PreferCopyEngine);

Expand All @@ -435,7 +435,7 @@ ur_result_t enqueueCommandBufferFillHelper(
ZeCommandList == CommandBuffer->ZeCopyCommandList) {
ze_event_handle_t ZeSignalPrevCommandEvent = nullptr;
UR_CALL(createSyncPointBetweenCopyAndCompute(CommandType, CommandBuffer,
isFirstNode, true /*isCopy=*/,
IsFirstNode, true /*isCopy=*/,
ZeSignalPrevCommandEvent));
if (ZeSignalPrevCommandEvent) {
ZeEventList.push_back(ZeSignalPrevCommandEvent);
Expand Down Expand Up @@ -585,13 +585,13 @@ void ur_exp_command_buffer_handle_t_::registerSyncPoint(

ze_command_list_handle_t
ur_exp_command_buffer_handle_t_::chooseCommandList(bool PreferCopyEngine) {
if (PreferCopyEngine && this->useCopyEngine()) {
if (PreferCopyEngine && useCopyEngine()) {
// We indicate that ZeCopyCommandList contains commands to be submitted.
this->MCopyCommandListEmpty = false;
return this->ZeCopyCommandList;
MCopyCommandListEmpty = false;
return ZeCopyCommandList;
}
this->MComputeCommandListEmpty = false;
return this->ZeComputeCommandList;
MComputeCommandListEmpty = false;
return ZeComputeCommandList;
}

ur_result_t ur_exp_command_buffer_handle_t_::getFenceForQueue(
Expand Down Expand Up @@ -1189,11 +1189,9 @@ ur_result_t urCommandBufferAppendKernelLaunchExp(
// used.
if (CommandBuffer->IsInOrderCmdList && CommandBuffer->ZeCopyCommandList) {
ze_event_handle_t ZeSignalPrevCommandEvent = nullptr;
bool isFirstNode{CommandBuffer->MComputeCommandListEmpty &&
CommandBuffer->MCopyCommandListEmpty};
UR_CALL(createSyncPointBetweenCopyAndCompute(
UR_COMMAND_KERNEL_LAUNCH, CommandBuffer, isFirstNode, false /*isCopy=*/,
ZeSignalPrevCommandEvent));
UR_COMMAND_KERNEL_LAUNCH, CommandBuffer, CommandBuffer->isFirstNode(),
false /*isCopy=*/, ZeSignalPrevCommandEvent));
if (ZeSignalPrevCommandEvent) {
ZeEventList.push_back(ZeSignalPrevCommandEvent);
}
Expand Down Expand Up @@ -1434,10 +1432,8 @@ ur_result_t urCommandBufferAppendUSMPrefetchExp(
// used.
if (CommandBuffer->ZeCopyCommandList) {
ze_event_handle_t ZeSignalPrevCommandEvent = nullptr;
bool isFirstNode{CommandBuffer->MComputeCommandListEmpty &&
CommandBuffer->MCopyCommandListEmpty};
UR_CALL(createSyncPointBetweenCopyAndCompute(
UR_COMMAND_KERNEL_LAUNCH, CommandBuffer, isFirstNode,
UR_COMMAND_KERNEL_LAUNCH, CommandBuffer, CommandBuffer->isFirstNode(),
false /*isCopy=*/, ZeSignalPrevCommandEvent));
if (ZeSignalPrevCommandEvent) {
ZE2UR_CALL(zeCommandListAppendWaitOnEvents,
Expand Down Expand Up @@ -1520,10 +1516,8 @@ ur_result_t urCommandBufferAppendUSMAdviseExp(
// used.
if (CommandBuffer->ZeCopyCommandList) {
ze_event_handle_t ZeSignalPrevCommandEvent = nullptr;
bool isFirstNode{CommandBuffer->MComputeCommandListEmpty &&
CommandBuffer->MCopyCommandListEmpty};
UR_CALL(createSyncPointBetweenCopyAndCompute(
UR_COMMAND_KERNEL_LAUNCH, CommandBuffer, isFirstNode,
UR_COMMAND_KERNEL_LAUNCH, CommandBuffer, CommandBuffer->isFirstNode(),
false /*isCopy=*/, ZeSignalPrevCommandEvent));
if (ZeSignalPrevCommandEvent) {
ZE2UR_CALL(zeCommandListAppendWaitOnEvents,
Expand Down
8 changes: 6 additions & 2 deletions source/adapters/level_zero/command_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ struct ur_exp_command_buffer_handle_t_ : public _ur_object {
return NextSyncPoint;
}

bool isFirstNode() const {
return MComputeCommandListEmpty && MCopyCommandListEmpty;
}

// Indicates if a copy engine is available for use
bool useCopyEngine() const { return ZeCopyCommandList != nullptr; }

Expand Down Expand Up @@ -110,11 +114,11 @@ struct ur_exp_command_buffer_handle_t_ : public _ur_object {
// This flag must be set to false if at least one copy command has been
// added to `ZeCopyCommandList`
bool MCopyCommandListEmpty = true;
// This flag must be set to false if at least one copy command has been
// This flag must be set to false if at least one compute command has been
// added to `ZeComputeCommandList`
bool MComputeCommandListEmpty = true;
// This flag tracks if the previous node submission was compute or copy type.
bool WasPrevCopyCommandList = false;
bool MWasPrevCopyCommandList = false;
// [WaitEvent Path only] Level Zero fences for each queue the command-buffer
// has been enqueued to. These should be destroyed when the command-buffer is
// released.
Expand Down