Inorder queues can use counter-based events which have better performance and provide early-reused semantics. Assisted by Claude.
108 lines
3.4 KiB
C++
108 lines
3.4 KiB
C++
//===--- Level Zero Target RTL Implementation -----------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Level Zero Event and Event Pool implementations.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "L0Event.h"
|
|
#include "L0Device.h"
|
|
#include "L0Trace.h"
|
|
|
|
namespace llvm::omp::target::plugin {
|
|
|
|
Expected<ze_event_handle_t> EventPoolTy::getEventLocked() {
|
|
if (Events.empty()) {
|
|
// Need to create a new L0 pool.
|
|
ze_event_pool_desc_t Desc{/* stype */ ZE_STRUCTURE_TYPE_EVENT_POOL_DESC,
|
|
/* pNext */ nullptr,
|
|
/* flags */ 0,
|
|
/* count */ 0};
|
|
Desc.flags = ZE_EVENT_POOL_FLAG_HOST_VISIBLE | Flags;
|
|
Desc.count = static_cast<uint32_t>(PoolSize);
|
|
|
|
ze_event_pool_counter_based_exp_desc_t CounterBasedDesc = {
|
|
ZE_STRUCTURE_TYPE_COUNTER_BASED_EVENT_POOL_EXP_DESC,
|
|
/* pNext */ nullptr,
|
|
/* flags */ 0};
|
|
CounterBasedDesc.flags = ZE_EVENT_POOL_COUNTER_BASED_EXP_FLAG_IMMEDIATE;
|
|
|
|
if (UseCounterBasedEvents)
|
|
Desc.pNext = &CounterBasedDesc;
|
|
|
|
ze_event_pool_handle_t Pool;
|
|
CALL_ZE_RET_ERROR(zeEventPoolCreate, Context, &Desc, 0, nullptr, &Pool);
|
|
Pools.push_back(Pool);
|
|
|
|
// Create events.
|
|
ze_event_desc_t EventDesc{ZE_STRUCTURE_TYPE_EVENT_DESC, nullptr, 0, 0, 0};
|
|
EventDesc.wait = 0;
|
|
EventDesc.signal = ZE_EVENT_SCOPE_FLAG_HOST;
|
|
uint32_t CreatedEvents = 0;
|
|
for (uint32_t EventIdx = 0; EventIdx < PoolSize; EventIdx++) {
|
|
EventDesc.index = EventIdx;
|
|
ze_event_handle_t Event;
|
|
ze_result_t RC;
|
|
CALL_ZE(RC, zeEventCreate, Pool, &EventDesc, &Event);
|
|
if (RC != ZE_RESULT_SUCCESS) {
|
|
// Log the error and skip this event.
|
|
ODBG(OLDT_Init) << "Warning: zeEventCreate failed at index " << EventIdx
|
|
<< " with code " << RC << ". Skipping this event.";
|
|
continue;
|
|
}
|
|
Events.push_back(Event);
|
|
CreatedEvents++;
|
|
}
|
|
PoolSize = CreatedEvents;
|
|
ODBG(OLDT_Init) << "Created a new event pool " << Pool << " with "
|
|
<< PoolSize << " events";
|
|
}
|
|
|
|
auto Ret = Events.back();
|
|
Events.pop_back();
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/// Return an event to the pool.
|
|
Error EventPoolTy::releaseEvent(ze_event_handle_t Event) {
|
|
std::lock_guard<std::mutex> Lock(*Mtx);
|
|
if (!UseCounterBasedEvents)
|
|
CALL_ZE_RET_ERROR(zeEventHostReset, Event);
|
|
Events.push_back(Event);
|
|
return Plugin::success();
|
|
}
|
|
|
|
Expected<L0EventTy *> EventPoolTy::getEventObject() {
|
|
std::lock_guard<std::mutex> Lock(*Mtx);
|
|
|
|
if (EventObjects.empty()) {
|
|
auto EventOrErr = getEventLocked();
|
|
if (!EventOrErr)
|
|
return EventOrErr.takeError();
|
|
auto Event = *EventOrErr;
|
|
auto *EventObj = new L0EventTy(Event, UseCounterBasedEvents);
|
|
return EventObj;
|
|
}
|
|
|
|
auto *Ret = EventObjects.back();
|
|
if (auto Err = Ret->reset())
|
|
return std::move(Err);
|
|
|
|
EventObjects.pop_back();
|
|
return Ret;
|
|
}
|
|
|
|
Error EventPoolTy::releaseEventObject(L0EventTy *EventObj) {
|
|
std::lock_guard<std::mutex> Lock(*Mtx);
|
|
EventObjects.push_back(EventObj);
|
|
return Plugin::success();
|
|
}
|
|
|
|
} // namespace llvm::omp::target::plugin
|