Inorder queues can use counter-based events which have better performance and provide early-reused semantics. Assisted by Claude.
138 lines
4.0 KiB
C++
138 lines
4.0 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 abstractions.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0EVENT_H
|
|
#define OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0EVENT_H
|
|
|
|
#include <level_zero/ze_api.h>
|
|
#include <memory>
|
|
#include <mutex>
|
|
|
|
#include "L0Defs.h"
|
|
#include "L0Trace.h"
|
|
|
|
namespace llvm::omp::target::plugin {
|
|
|
|
class L0QueueTy;
|
|
|
|
class L0EventTy {
|
|
ze_event_handle_t ZeEvent = nullptr;
|
|
bool CounterBased = false;
|
|
L0QueueTy *Queue = nullptr;
|
|
|
|
public:
|
|
L0EventTy(ze_event_handle_t ZeEvent, bool CounterBased)
|
|
: ZeEvent(ZeEvent), CounterBased(CounterBased) {}
|
|
ze_event_handle_t getZeEvent() const { return ZeEvent; }
|
|
L0QueueTy *getQueue() const { return Queue; }
|
|
|
|
Error reset() {
|
|
Queue = nullptr;
|
|
if (!CounterBased)
|
|
CALL_ZE_RET_ERROR(zeEventHostReset, ZeEvent);
|
|
return Plugin::success();
|
|
}
|
|
|
|
void setQueue(L0QueueTy &Q) { Queue = &Q; }
|
|
|
|
Error synchronize() {
|
|
CALL_ZE_RET_ERROR(zeEventHostSynchronize, ZeEvent, L0DefaultTimeout);
|
|
return Plugin::success();
|
|
}
|
|
|
|
Expected<bool> isComplete() {
|
|
ze_result_t Result;
|
|
|
|
CALL_ZE(Result, zeEventQueryStatus, ZeEvent);
|
|
if (Result == ZE_RESULT_SUCCESS)
|
|
return true;
|
|
if (Result == ZE_RESULT_NOT_READY)
|
|
return false;
|
|
return Plugin::error(ErrorCode::UNKNOWN, "failed to query event status: %s",
|
|
getZeErrorName(Result));
|
|
}
|
|
};
|
|
|
|
/// Common event pool used in the plugin. This event pool assumes all events
|
|
/// from the pool are host-visible and use the same event pool flag.
|
|
class EventPoolTy {
|
|
/// Size of L0 event pool created on demand.
|
|
size_t PoolSize = 64;
|
|
|
|
/// Context of the events.
|
|
ze_context_handle_t Context = nullptr;
|
|
|
|
/// Additional event pool flags common to this pool.
|
|
uint32_t Flags = 0;
|
|
|
|
/// Whether counter-based events are being used (don't need reset).
|
|
bool UseCounterBasedEvents = false;
|
|
|
|
/// Protection.
|
|
std::unique_ptr<std::mutex> Mtx;
|
|
|
|
/// Created L0 event pools.
|
|
llvm::SmallVector<ze_event_pool_handle_t> Pools;
|
|
|
|
/// L0 events cache.
|
|
llvm::SmallVector<ze_event_handle_t> Events;
|
|
|
|
/// L0 event objects cache.
|
|
llvm::SmallVector<L0EventTy *> EventObjects;
|
|
|
|
// Internal method to get an event from the pool. The caller must hold the
|
|
// lock.
|
|
Expected<ze_event_handle_t> getEventLocked();
|
|
|
|
public:
|
|
/// Initialize context, flags, and mutex.
|
|
Error init(ze_context_handle_t ContextIn, bool UseCounterBased,
|
|
uint32_t FlagsIn) {
|
|
Context = ContextIn;
|
|
Flags = FlagsIn;
|
|
UseCounterBasedEvents = UseCounterBased;
|
|
Mtx.reset(new std::mutex);
|
|
return Plugin::success();
|
|
}
|
|
|
|
/// Destroys L0 resources.
|
|
Error deinit() {
|
|
for (auto *EventObj : EventObjects)
|
|
delete EventObj;
|
|
for (auto E : Events)
|
|
CALL_ZE_RET_ERROR(zeEventDestroy, E);
|
|
for (auto P : Pools)
|
|
CALL_ZE_RET_ERROR(zeEventPoolDestroy, P);
|
|
return Plugin::success();
|
|
}
|
|
|
|
/// Get a L0 Event (ze_event_handle_t) from the pool.
|
|
Expected<ze_event_handle_t> getEvent() {
|
|
std::lock_guard<std::mutex> Lock(*Mtx);
|
|
return getEventLocked();
|
|
}
|
|
/// Get an L0EventTy object that wraps a ze_event_handle_t from the pool.
|
|
/// This is the preferred way to get an event unless a raw event is really
|
|
/// needed.
|
|
Expected<L0EventTy *> getEventObject();
|
|
|
|
/// Return a ze_event_handle_t to the pool.
|
|
Error releaseEvent(ze_event_handle_t Event);
|
|
/// Returns an L0EventTy object to the pool so it can be reused. This does not
|
|
/// return the underlying ze_event_handle_t to the handle pool.
|
|
Error releaseEventObject(L0EventTy *EventObj);
|
|
};
|
|
|
|
} // namespace llvm::omp::target::plugin
|
|
|
|
#endif // OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_LEVEL_ZERO_L0EVENT_H
|