CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
886 lines
34 KiB
C++
886 lines
34 KiB
C++
//===-- OmptTracing.cpp - Target independent OpenMP target RTL --- C++ -*--===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Implementation of OMPT tracing interfaces for target independent layer
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifdef OMPT_SUPPORT
|
|
|
|
#include "OpenMP/OMPT/OmptTracing.h"
|
|
#include "OpenMP/OMPT/Callback.h"
|
|
#include "OpenMP/OMPT/Interface.h"
|
|
#include "OpenMP/OMPT/OmptTracingBuffer.h"
|
|
#include "PluginManager.h"
|
|
#include "Shared/Debug.h"
|
|
#include "omp-tools.h"
|
|
|
|
#include "llvm/Support/DynamicLibrary.h"
|
|
|
|
#include <atomic>
|
|
#include <cassert>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <thread>
|
|
|
|
#pragma push_macro("DEBUG_PREFIX")
|
|
#undef DEBUG_PREFIX
|
|
#define DEBUG_PREFIX "OMPT"
|
|
|
|
using namespace llvm::omp::target::ompt;
|
|
|
|
std::mutex llvm::omp::target::ompt::DeviceAccessMutex;
|
|
std::mutex llvm::omp::target::ompt::TraceAccessMutex;
|
|
std::mutex llvm::omp::target::ompt::TraceControlMutex;
|
|
std::mutex llvm::omp::target::ompt::TraceHashThreadMutex;
|
|
std::mutex llvm::omp::target::ompt::BufferManagementFnMutex;
|
|
|
|
std::unordered_map<int /*DeviceId*/, std::pair<ompt_callback_buffer_request_t,
|
|
ompt_callback_buffer_complete_t>>
|
|
llvm::omp::target::ompt::BufferManagementFns;
|
|
|
|
thread_local uint32_t llvm::omp::target::ompt::TraceRecordNumGrantedTeams = 0;
|
|
thread_local uint64_t llvm::omp::target::ompt::TraceRecordStartTime = 0;
|
|
thread_local uint64_t llvm::omp::target::ompt::TraceRecordStopTime = 0;
|
|
thread_local uint64_t llvm::omp::target::ompt::ThreadId =
|
|
std::numeric_limits<uint64_t>::max();
|
|
|
|
std::map<int32_t, uint64_t> llvm::omp::target::ompt::TracedDevices;
|
|
|
|
bool llvm::omp::target::ompt::TracingActive = false;
|
|
|
|
void llvm::omp::target::ompt::resetTimestamp(uint64_t *T) { *T = 0; }
|
|
|
|
ompt_callback_buffer_request_t
|
|
llvm::omp::target::ompt::getBufferRequestFn(int DeviceId) {
|
|
std::unique_lock<std::mutex> Lock(BufferManagementFnMutex);
|
|
auto BufferMgrItr = BufferManagementFns.find(DeviceId);
|
|
if (BufferMgrItr == BufferManagementFns.end()) {
|
|
return nullptr;
|
|
}
|
|
return BufferMgrItr->second.first;
|
|
}
|
|
|
|
ompt_callback_buffer_complete_t
|
|
llvm::omp::target::ompt::getBufferCompleteFn(int DeviceId) {
|
|
std::unique_lock<std::mutex> Lock(BufferManagementFnMutex);
|
|
auto BufferMgrItr = BufferManagementFns.find(DeviceId);
|
|
if (BufferMgrItr == BufferManagementFns.end()) {
|
|
return nullptr;
|
|
}
|
|
return BufferMgrItr->second.second;
|
|
}
|
|
|
|
void llvm::omp::target::ompt::setBufferManagementFns(
|
|
int DeviceId, ompt_callback_buffer_request_t ReqFn,
|
|
ompt_callback_buffer_complete_t CmpltFn) {
|
|
std::unique_lock<std::mutex> Lock(BufferManagementFnMutex);
|
|
auto BufferMgrItr = BufferManagementFns.find(DeviceId);
|
|
if (BufferMgrItr != BufferManagementFns.end()) {
|
|
REPORT() << "Buffer request and complete functions already exist for device "
|
|
<< DeviceId << "ignoring ...";
|
|
return;
|
|
}
|
|
BufferManagementFns[DeviceId] = std::make_pair(ReqFn, CmpltFn);
|
|
}
|
|
|
|
void llvm::omp::target::ompt::removeBufferManagementFns(int DeviceId) {
|
|
std::unique_lock<std::mutex> Lock(BufferManagementFnMutex);
|
|
auto BufferMgrItr = BufferManagementFns.find(DeviceId);
|
|
if (BufferMgrItr == BufferManagementFns.end()) {
|
|
REPORT() << "Buffer request and complete functions don't exist for device "
|
|
<< DeviceId << "ignoring ...";
|
|
return;
|
|
}
|
|
BufferManagementFns.erase(BufferMgrItr);
|
|
}
|
|
|
|
bool llvm::omp::target::ompt::isAllDeviceTracingStopped() {
|
|
std::unique_lock<std::mutex> Lock(BufferManagementFnMutex);
|
|
return BufferManagementFns.empty();
|
|
}
|
|
|
|
void llvm::omp::target::ompt::ompt_callback_buffer_request(
|
|
int DeviceId, ompt_buffer_t **BufferPtr, size_t *Bytes) {
|
|
if (auto Fn = getBufferRequestFn(DeviceId))
|
|
Fn(DeviceId, BufferPtr, Bytes);
|
|
}
|
|
|
|
void llvm::omp::target::ompt::ompt_callback_buffer_complete(
|
|
int DeviceId, ompt_buffer_t *Buffer, size_t Bytes,
|
|
ompt_buffer_cursor_t BeginCursor, int BufferOwned) {
|
|
if (auto Fn = getBufferCompleteFn(DeviceId))
|
|
Fn(DeviceId, Buffer, Bytes, BeginCursor, BufferOwned);
|
|
}
|
|
|
|
inline void setDeviceTracing(uint64_t &TracingTypes) {
|
|
// Set bit 0 to indicate generally enabled device tracing.
|
|
TracingTypes |= 1UL;
|
|
}
|
|
|
|
inline void resetDeviceTracing(uint64_t &TracingTypes) {
|
|
// Reset bit 0 to indicate generally disabled device tracing.
|
|
TracingTypes &= ~(1UL);
|
|
}
|
|
|
|
inline bool checkDeviceTracingState(const uint64_t &TracingTypes) {
|
|
// Return state of bit 0 to indicate if device is actively traced.
|
|
return TracingTypes & 1UL;
|
|
}
|
|
|
|
void llvm::omp::target::ompt::enableDeviceTracing(int DeviceId) {
|
|
std::unique_lock<std::mutex> Lock(DeviceAccessMutex);
|
|
auto Device = TracedDevices.find(DeviceId);
|
|
if (Device == TracedDevices.end()) {
|
|
uint64_t TracingTypes{0};
|
|
setDeviceTracing(TracingTypes);
|
|
TracedDevices.emplace(DeviceId, TracingTypes);
|
|
} else
|
|
setDeviceTracing(Device->second);
|
|
// In any case: at least one device is traced
|
|
TracingActive = true;
|
|
}
|
|
|
|
void llvm::omp::target::ompt::disableDeviceTracing(int DeviceId) {
|
|
std::unique_lock<std::mutex> Lock(DeviceAccessMutex);
|
|
auto Device = TracedDevices.find(DeviceId);
|
|
if (Device == TracedDevices.end()) {
|
|
uint64_t TracingTypes{0};
|
|
resetDeviceTracing(TracingTypes);
|
|
TracedDevices.emplace(DeviceId, TracingTypes);
|
|
} else
|
|
resetDeviceTracing(Device->second);
|
|
|
|
// Check for actively traced devices
|
|
for (auto &Dev : TracedDevices)
|
|
if (checkDeviceTracingState(Dev.second))
|
|
return;
|
|
|
|
// If no device is currently traced: set global tracing flag to false
|
|
TracingActive = false;
|
|
}
|
|
|
|
bool llvm::omp::target::ompt::isTracingEnabled(int DeviceId,
|
|
unsigned int EventTy) {
|
|
return TracingActive && isTracedDevice(DeviceId) &&
|
|
isTracingTypeGroupEnabled(DeviceId, EventTy);
|
|
}
|
|
|
|
bool llvm::omp::target::ompt::isTracedDevice(int DeviceId) {
|
|
std::unique_lock<std::mutex> Lock(DeviceAccessMutex);
|
|
auto Device = TracedDevices.find(DeviceId);
|
|
if (Device != TracedDevices.end())
|
|
return checkDeviceTracingState(Device->second);
|
|
|
|
return false;
|
|
}
|
|
|
|
bool llvm::omp::target::ompt::isTracingTypeEnabled(int DeviceId,
|
|
unsigned int EventTy) {
|
|
std::unique_lock<std::mutex> Lock(DeviceAccessMutex);
|
|
// Make sure we do not shift more than std::numeric_limits<uint64_t>::digits
|
|
assert(EventTy < 64 && "Shift limit exceeded: EventTy must be less than 64");
|
|
auto Device = TracedDevices.find(DeviceId);
|
|
if (Device != TracedDevices.end() && EventTy < 64)
|
|
return (Device->second & (1UL << EventTy));
|
|
return false;
|
|
}
|
|
|
|
bool llvm::omp::target::ompt::isTracingTypeGroupEnabled(int DeviceId,
|
|
unsigned int EventTy) {
|
|
std::unique_lock<std::mutex> Lock(DeviceAccessMutex);
|
|
// Make sure we do not shift more than std::numeric_limits<uint64_t>::digits
|
|
assert(EventTy < 64 && "Shift limit exceeded: EventTy must be less than 64");
|
|
auto Device = TracedDevices.find(DeviceId);
|
|
if (Device != TracedDevices.end() && EventTy < 64) {
|
|
auto TracedEvents = Device->second;
|
|
switch (EventTy) {
|
|
case ompt_callbacks_t::ompt_callback_target:
|
|
case ompt_callbacks_t::ompt_callback_target_emi:
|
|
return ((TracedEvents & (1UL << ompt_callback_target))) ||
|
|
((TracedEvents & (1UL << ompt_callback_target_emi)));
|
|
case ompt_callbacks_t::ompt_callback_target_data_op:
|
|
case ompt_callbacks_t::ompt_callback_target_data_op_emi:
|
|
return ((TracedEvents & (1UL << ompt_callback_target_data_op))) ||
|
|
((TracedEvents & (1UL << ompt_callback_target_data_op_emi)));
|
|
case ompt_callbacks_t::ompt_callback_target_submit:
|
|
case ompt_callbacks_t::ompt_callback_target_submit_emi:
|
|
return ((TracedEvents & (1UL << ompt_callback_target_submit))) ||
|
|
((TracedEvents & (1UL << ompt_callback_target_submit_emi)));
|
|
// Special case: EventTy == 0 -> Check all EventTy
|
|
case 0:
|
|
return ((TracedEvents & (1UL << ompt_callback_target))) ||
|
|
((TracedEvents & (1UL << ompt_callback_target_emi))) ||
|
|
((TracedEvents & (1UL << ompt_callback_target_data_op))) ||
|
|
((TracedEvents & (1UL << ompt_callback_target_data_op_emi))) ||
|
|
((TracedEvents & (1UL << ompt_callback_target_submit))) ||
|
|
((TracedEvents & (1UL << ompt_callback_target_submit_emi)));
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void llvm::omp::target::ompt::setTracingTypeEnabled(uint64_t &TracedEventTy,
|
|
bool Enable,
|
|
unsigned int EventTy) {
|
|
// Make sure we do not shift more than std::numeric_limits<uint64_t>::digits
|
|
assert(EventTy < 64 && "Shift limit exceeded: EventTy must be less than 64");
|
|
if (EventTy < 64) {
|
|
if (Enable)
|
|
TracedEventTy |= (1UL << EventTy);
|
|
else
|
|
TracedEventTy &= ~(1UL << EventTy);
|
|
}
|
|
}
|
|
|
|
ompt_set_result_t
|
|
llvm::omp::target::ompt::setTraceEventTy(int DeviceId, unsigned int Enable,
|
|
unsigned int EventTy) {
|
|
if (DeviceId < 0) {
|
|
REPORT() << "Failed to set trace event type for DeviceId=" << DeviceId;
|
|
return ompt_set_never;
|
|
}
|
|
|
|
ODBG(ODT_Tool) << "Executing setTraceEventTy: DeviceId=" << DeviceId
|
|
<< " Enable=" << Enable << " EventTy=" << EventTy;
|
|
|
|
std::unique_lock<std::mutex> Lock(DeviceAccessMutex);
|
|
if (TracedDevices.find(DeviceId) == TracedDevices.end())
|
|
TracedDevices.emplace(DeviceId, 0UL);
|
|
|
|
auto &TracedEventTy = TracedDevices[DeviceId];
|
|
bool Enabled = Enable > 0;
|
|
if (EventTy == 0) {
|
|
// Set / reset all supported types
|
|
setTracingTypeEnabled(TracedEventTy, Enabled,
|
|
ompt_callbacks_t::ompt_callback_target);
|
|
setTracingTypeEnabled(TracedEventTy, Enabled,
|
|
ompt_callbacks_t::ompt_callback_target_data_op);
|
|
setTracingTypeEnabled(TracedEventTy, Enabled,
|
|
ompt_callbacks_t::ompt_callback_target_submit);
|
|
setTracingTypeEnabled(TracedEventTy, Enabled,
|
|
ompt_callbacks_t::ompt_callback_target_emi);
|
|
setTracingTypeEnabled(TracedEventTy, Enabled,
|
|
ompt_callbacks_t::ompt_callback_target_data_op_emi);
|
|
setTracingTypeEnabled(TracedEventTy, Enabled,
|
|
ompt_callbacks_t::ompt_callback_target_submit_emi);
|
|
|
|
if (Enabled) {
|
|
// Event subset is enabled
|
|
return ompt_set_sometimes;
|
|
} else {
|
|
// All events are disabled
|
|
return ompt_set_always;
|
|
}
|
|
}
|
|
|
|
switch (EventTy) {
|
|
case ompt_callbacks_t::ompt_callback_target:
|
|
case ompt_callbacks_t::ompt_callback_target_data_op:
|
|
case ompt_callbacks_t::ompt_callback_target_submit:
|
|
case ompt_callbacks_t::ompt_callback_target_emi:
|
|
case ompt_callbacks_t::ompt_callback_target_data_op_emi:
|
|
case ompt_callbacks_t::ompt_callback_target_submit_emi: {
|
|
setTracingTypeEnabled(TracedEventTy, Enabled, EventTy);
|
|
return ompt_set_always;
|
|
}
|
|
default: {
|
|
if (Enabled) {
|
|
// Unimplemented
|
|
return ompt_set_never;
|
|
} else {
|
|
// Always disabled anyways
|
|
return ompt_set_always;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
uint64_t llvm::omp::target::ompt::getThreadId() {
|
|
// Grab the value from thread local storage, if valid.
|
|
if (ThreadId != std::numeric_limits<uint64_t>::max())
|
|
return ThreadId;
|
|
// Otherwise set it, protecting the hash with a lock.
|
|
std::unique_lock<std::mutex> Lock(TraceHashThreadMutex);
|
|
ThreadId = std::hash<std::thread::id>()(std::this_thread::get_id());
|
|
return ThreadId;
|
|
}
|
|
|
|
void Interface::setTraceRecordCommon(ompt_record_ompt_t *DataPtr,
|
|
ompt_callbacks_t CallbackType) {
|
|
DataPtr->type = CallbackType;
|
|
|
|
if (CallbackType == ompt_callback_target)
|
|
DataPtr->time = 0; // Currently, no consumer, so no need to set it
|
|
else {
|
|
DataPtr->time = TraceRecordStartTime;
|
|
resetTimestamp(&TraceRecordStartTime);
|
|
}
|
|
|
|
DataPtr->thread_id = getThreadId();
|
|
DataPtr->target_id = TargetData.value;
|
|
}
|
|
|
|
void Interface::setTraceRecordTargetDataOp(ompt_record_target_data_op_t *Record,
|
|
ompt_target_data_op_t DataOpType,
|
|
void *SrcAddr, int64_t SrcDeviceNum,
|
|
void *DstAddr, int64_t DstDeviceNum,
|
|
size_t Bytes, void *CodePtr) {
|
|
Record->host_op_id = HostOpId;
|
|
Record->optype = DataOpType;
|
|
Record->src_addr = SrcAddr;
|
|
Record->src_device_num = SrcDeviceNum;
|
|
Record->dest_addr = DstAddr;
|
|
Record->dest_device_num = DstDeviceNum;
|
|
Record->bytes = Bytes;
|
|
|
|
Record->end_time = TraceRecordStopTime;
|
|
resetTimestamp(&TraceRecordStopTime);
|
|
|
|
Record->codeptr_ra = CodePtr;
|
|
}
|
|
|
|
void Interface::setTraceRecordTargetKernel(ompt_record_target_kernel_t *Record,
|
|
unsigned int NumTeams) {
|
|
Record->host_op_id = HostOpId;
|
|
Record->requested_num_teams = NumTeams;
|
|
Record->granted_num_teams = TraceRecordNumGrantedTeams;
|
|
|
|
Record->end_time = TraceRecordStopTime;
|
|
resetTimestamp(&TraceRecordStopTime);
|
|
}
|
|
|
|
void Interface::setTraceRecordTarget(ompt_record_target_t *Record,
|
|
int64_t DeviceId, ompt_target_t TargetKind,
|
|
ompt_scope_endpoint_t Endpoint,
|
|
void *CodePtr) {
|
|
Record->kind = TargetKind;
|
|
Record->endpoint = Endpoint;
|
|
Record->device_num = DeviceId;
|
|
assert(TaskData);
|
|
Record->task_id = TaskData->value;
|
|
Record->target_id = TargetData.value;
|
|
Record->codeptr_ra = CodePtr;
|
|
}
|
|
|
|
void Interface::startTargetDataAllocTrace(int64_t DeviceId, void *HstPtrBegin,
|
|
void **TgtPtrBegin, size_t Size,
|
|
void *Code) {}
|
|
|
|
ompt_record_ompt_t *Interface::stopTargetDataAllocTrace(int64_t DeviceId,
|
|
void *HstPtrBegin,
|
|
void **TgtPtrBegin,
|
|
size_t Size,
|
|
void *Code) {
|
|
if (!isTracingEnabled(DeviceId, ompt_callback_target_data_op))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr = (ompt_record_ompt_t *)TRM->assignCursor(
|
|
ompt_callback_target_data_op, DeviceId);
|
|
|
|
// This event will not be traced
|
|
if (DataPtr == nullptr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target_data_op);
|
|
setTraceRecordTargetDataOp(
|
|
&DataPtr->record.target_data_op, ompt_target_data_alloc, HstPtrBegin,
|
|
/*SrcDeviceNum=*/omp_initial_device, *TgtPtrBegin, DeviceId, Size, Code);
|
|
|
|
// The trace record has been created, mark it ready for delivery to the tool
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
ODBG(ODT_Tool) << "Generated trace record: " << DataPtr
|
|
<< " (ompt_target_data_alloc)";
|
|
return DataPtr;
|
|
}
|
|
|
|
void Interface::startTargetDataDeleteTrace(int64_t DeviceId, void *TgtPtrBegin,
|
|
void *Code) {}
|
|
|
|
ompt_record_ompt_t *Interface::stopTargetDataDeleteTrace(int64_t DeviceId,
|
|
void *TgtPtrBegin,
|
|
void *Code) {
|
|
if (!isTracingEnabled(DeviceId, ompt_callback_target_data_op))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr = (ompt_record_ompt_t *)TRM->assignCursor(
|
|
ompt_callback_target_data_op, DeviceId);
|
|
|
|
// This event will not be traced
|
|
if (DataPtr == nullptr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target_data_op);
|
|
setTraceRecordTargetDataOp(&DataPtr->record.target_data_op,
|
|
ompt_target_data_delete, TgtPtrBegin, DeviceId,
|
|
/*DstAddr=*/nullptr,
|
|
/*DstDeviceNum=*/omp_initial_device, /*Bytes=*/0,
|
|
Code);
|
|
|
|
// The trace record has been created, mark it ready for delivery to the tool
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
ODBG(ODT_Tool) << "Generated trace record: " << DataPtr
|
|
<< " (ompt_target_data_delete)";
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *
|
|
Interface::startTargetDataSubmitTrace(int64_t SrcDeviceId, void *SrcPtrBegin,
|
|
int64_t DstDeviceId, void *DstPtrBegin,
|
|
size_t Size, void *Code) {
|
|
if (!isTracingEnabled(DstDeviceId, ompt_callback_target_data_op))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr = (ompt_record_ompt_t *)TRM->assignCursor(
|
|
ompt_callback_target_data_op, DstDeviceId);
|
|
|
|
// This event will not be traced
|
|
if (DataPtr == nullptr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target_data_op);
|
|
DataPtr->time = 0; // Set to sanity value and let "stop" function fix it
|
|
|
|
// Set some of the data-op specific fields here
|
|
setTraceRecordTargetDataOp(&DataPtr->record.target_data_op,
|
|
ompt_target_data_transfer_to_device, SrcPtrBegin,
|
|
SrcDeviceId, DstPtrBegin, DstDeviceId, Size, Code);
|
|
|
|
ODBG(ODT_Tool) << "OMPT-Async: Returning data trace record buf ptr " << DataPtr;
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *
|
|
Interface::startTargetDataRetrieveTrace(int64_t SrcDeviceId, void *SrcPtrBegin,
|
|
int64_t DstDeviceId, void *DstPtrBegin,
|
|
size_t Size, void *Code) {
|
|
if (!isTracingEnabled(SrcDeviceId, ompt_callback_target_data_op))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr = (ompt_record_ompt_t *)TRM->assignCursor(
|
|
ompt_callback_target_data_op, SrcDeviceId);
|
|
|
|
if (!DataPtr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target_data_op);
|
|
DataPtr->time = 0; // Set to sanity value and let "stop" function fix it
|
|
|
|
// Set some of the data-op specific fields here
|
|
setTraceRecordTargetDataOp(&DataPtr->record.target_data_op,
|
|
ompt_target_data_transfer_from_device, SrcPtrBegin,
|
|
SrcDeviceId, DstPtrBegin, DstDeviceId, Size, Code);
|
|
|
|
ODBG(ODT_Tool) << "OMPT-Async: Returning data trace record buf ptr " << DataPtr;
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *Interface::stopTargetDataMovementTraceAsync(
|
|
ompt_record_ompt_t *DataPtr, uint64_t NanosStart, uint64_t NanosEnd) {
|
|
// Finalize the data that comes from the plugin.
|
|
DataPtr->time = NanosStart;
|
|
auto Record = static_cast<ompt_record_target_data_op_t *>(
|
|
&DataPtr->record.target_data_op);
|
|
Record->end_time = NanosEnd;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
// The trace record has been created, mark it ready for delivery to the tool
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
ODBG(ODT_Tool) << "OMPT-Async: Completed target_data trace record " << DataPtr;
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *Interface::startTargetSubmitTrace(int64_t DeviceId,
|
|
unsigned int NumTeams) {
|
|
if (!isTracingEnabled(DeviceId, ompt_callback_target_submit))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr = (ompt_record_ompt_t *)TRM->assignCursor(
|
|
ompt_callback_target_submit, DeviceId);
|
|
|
|
// Set all known entries and leave remaining to the stop function
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target_submit);
|
|
DataPtr->time = 0; // Set to sanity value and let "stop" function fix it
|
|
// Kernel specific things
|
|
DataPtr->record.target_kernel.requested_num_teams = NumTeams;
|
|
DataPtr->record.target_kernel.host_op_id = getHostOpId();
|
|
|
|
// May be null if event is not traced
|
|
ODBG(ODT_Tool) << "OMPT-Async: Returning kernel trace record buf ptr " << DataPtr;
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *
|
|
Interface::stopTargetSubmitTraceAsync(ompt_record_ompt_t *DataPtr,
|
|
unsigned int NumTeams,
|
|
uint64_t NanosStart, uint64_t NanosStop) {
|
|
// Common fields
|
|
DataPtr->time = NanosStart;
|
|
// Submit specific
|
|
DataPtr->record.target_kernel.end_time = NanosStop;
|
|
DataPtr->record.target_kernel.granted_num_teams = NumTeams;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
// Ready Record
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
ODBG(ODT_Tool) << "OMPT-Async: Completed trace record buf ptr " << DataPtr;
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *Interface::startTargetDataEnterTrace(int64_t DeviceId,
|
|
void *CodePtr) {
|
|
if (!isTracingEnabled(DeviceId, ompt_callback_target))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr =
|
|
(ompt_record_ompt_t *)TRM->assignCursor(ompt_callback_target, DeviceId);
|
|
|
|
// This event will not be traced
|
|
if (DataPtr == nullptr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target);
|
|
setTraceRecordTarget(&DataPtr->record.target, DeviceId,
|
|
ompt_target_enter_data, ompt_scope_begin, CodePtr);
|
|
|
|
// The trace record has been created, mark it ready for delivery to the tool
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
ODBG(ODT_Tool) << "Returning trace record buf ptr " << DataPtr
|
|
<< " (ompt_target_enter_data)";
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *Interface::stopTargetDataEnterTrace(int64_t DeviceId,
|
|
void *CodePtr) {
|
|
if (!isTracingEnabled(DeviceId, ompt_callback_target))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr =
|
|
(ompt_record_ompt_t *)TRM->assignCursor(ompt_callback_target, DeviceId);
|
|
|
|
// This event will not be traced
|
|
if (DataPtr == nullptr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target);
|
|
setTraceRecordTarget(&DataPtr->record.target, DeviceId,
|
|
ompt_target_enter_data, ompt_scope_end, CodePtr);
|
|
|
|
// The trace record has been created, mark it ready for delivery to the tool
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
ODBG(ODT_Tool) << "Generated trace record " << DataPtr
|
|
<< " (ompt_target_enter_data)";
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *Interface::startTargetDataExitTrace(int64_t DeviceId,
|
|
void *CodePtr) {
|
|
if (!isTracingEnabled(DeviceId, ompt_callback_target))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr =
|
|
(ompt_record_ompt_t *)TRM->assignCursor(ompt_callback_target, DeviceId);
|
|
|
|
// This event will not be traced
|
|
if (DataPtr == nullptr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target);
|
|
setTraceRecordTarget(&DataPtr->record.target, DeviceId, ompt_target_exit_data,
|
|
ompt_scope_begin, CodePtr);
|
|
|
|
// The trace record has been created, mark it ready for delivery to the tool
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
ODBG(ODT_Tool) << "Returning trace record buf ptr " << DataPtr
|
|
<< " (ompt_target_exit_data)";
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *Interface::stopTargetDataExitTrace(int64_t DeviceId,
|
|
void *CodePtr) {
|
|
if (!isTracingEnabled(DeviceId, ompt_callback_target))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr =
|
|
(ompt_record_ompt_t *)TRM->assignCursor(ompt_callback_target, DeviceId);
|
|
|
|
// This event will not be traced
|
|
if (DataPtr == nullptr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target);
|
|
setTraceRecordTarget(&DataPtr->record.target, DeviceId, ompt_target_exit_data,
|
|
ompt_scope_end, CodePtr);
|
|
|
|
// The trace record has been created, mark it ready for delivery to the tool
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
ODBG(ODT_Tool) << "Generated trace record " << DataPtr
|
|
<< " (ompt_target_exit_data)";
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *Interface::startTargetUpdateTrace(int64_t DeviceId,
|
|
void *CodePtr) {
|
|
if (!isTracingEnabled(DeviceId, ompt_callback_target))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr =
|
|
(ompt_record_ompt_t *)TRM->assignCursor(ompt_callback_target, DeviceId);
|
|
|
|
// This event will not be traced
|
|
if (DataPtr == nullptr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target);
|
|
setTraceRecordTarget(&DataPtr->record.target, DeviceId, ompt_target_update,
|
|
ompt_scope_begin, CodePtr);
|
|
|
|
// The trace record has been created, mark it ready for delivery to the tool
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
ODBG(ODT_Tool) << "Returning trace record buf ptr " << DataPtr
|
|
<< " (ompt_target_update)";
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *Interface::stopTargetUpdateTrace(int64_t DeviceId,
|
|
void *CodePtr) {
|
|
if (!isTracingEnabled(DeviceId, ompt_callback_target))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr =
|
|
(ompt_record_ompt_t *)TRM->assignCursor(ompt_callback_target, DeviceId);
|
|
|
|
// This event will not be traced
|
|
if (DataPtr == nullptr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target);
|
|
setTraceRecordTarget(&DataPtr->record.target, DeviceId, ompt_target_update,
|
|
ompt_scope_end, CodePtr);
|
|
|
|
// The trace record has been created, mark it ready for delivery to the tool
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
ODBG(ODT_Tool) << "Generated trace record " << DataPtr
|
|
<< " (ompt_target_update)";
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *Interface::startTargetTrace(int64_t DeviceId,
|
|
void *CodePtr) {
|
|
if (!isTracingEnabled(DeviceId, ompt_callback_target))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr =
|
|
(ompt_record_ompt_t *)TRM->assignCursor(ompt_callback_target, DeviceId);
|
|
|
|
// This event will not be traced
|
|
if (DataPtr == nullptr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target);
|
|
setTraceRecordTarget(&DataPtr->record.target, DeviceId, ompt_target,
|
|
ompt_scope_begin, CodePtr);
|
|
|
|
// The trace record has been created, mark it ready for delivery to the tool
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
ODBG(ODT_Tool) << "Returning trace record buf ptr " << DataPtr
|
|
<< " (ompt_target)";
|
|
return DataPtr;
|
|
}
|
|
|
|
ompt_record_ompt_t *Interface::stopTargetTrace(int64_t DeviceId,
|
|
void *CodePtr) {
|
|
if (!isTracingEnabled(DeviceId, ompt_callback_target))
|
|
return nullptr;
|
|
|
|
assert(PM && "Plugin manager not initialized");
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
ompt_record_ompt_t *DataPtr =
|
|
(ompt_record_ompt_t *)TRM->assignCursor(ompt_callback_target, DeviceId);
|
|
|
|
// This event will not be traced
|
|
if (DataPtr == nullptr)
|
|
return nullptr;
|
|
|
|
setTraceRecordCommon(DataPtr, ompt_callback_target);
|
|
setTraceRecordTarget(&DataPtr->record.target, DeviceId, ompt_target,
|
|
ompt_scope_end, CodePtr);
|
|
|
|
// The trace record has been created, mark it ready for delivery to the tool
|
|
TRM->setTRStatus(DataPtr, OmptTracingBufferMgr::TR_ready);
|
|
|
|
ODBG(ODT_Tool) << "Generated trace record " << DataPtr
|
|
<< " (ompt_target)";
|
|
return DataPtr;
|
|
}
|
|
|
|
extern "C" {
|
|
// Device-independent entry point for ompt_set_trace_ompt
|
|
ompt_set_result_t libomptarget_ompt_set_trace_ompt(int DeviceId,
|
|
unsigned int Enable,
|
|
unsigned int EventTy) {
|
|
std::unique_lock<std::mutex> Lock(TraceAccessMutex);
|
|
return llvm::omp::target::ompt::setTraceEventTy(DeviceId, Enable, EventTy);
|
|
}
|
|
|
|
// Device-independent entry point for ompt_start_trace
|
|
int libomptarget_ompt_start_trace(int DeviceId,
|
|
ompt_callback_buffer_request_t Request,
|
|
ompt_callback_buffer_complete_t Complete) {
|
|
if (!PM) {
|
|
REPORT() << "Failed to start trace for DeviceId="
|
|
<< DeviceId << " (invalid plugin manager)";
|
|
// Indicate failure
|
|
return 0;
|
|
}
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
std::unique_lock<std::mutex> Lock(TraceControlMutex);
|
|
if (Request && Complete) {
|
|
// Set buffer related functions
|
|
llvm::omp::target::ompt::setBufferManagementFns(DeviceId, Request,
|
|
Complete);
|
|
llvm::omp::target::ompt::enableDeviceTracing(DeviceId);
|
|
TRM->startHelperThreads();
|
|
// Success
|
|
return 1;
|
|
}
|
|
// Failure
|
|
return 0;
|
|
}
|
|
|
|
// Device-independent entry point for ompt_flush_trace
|
|
int libomptarget_ompt_flush_trace(int DeviceId) {
|
|
if (!PM) {
|
|
REPORT() << "Failed to flush trace for DeviceId="
|
|
<< DeviceId << " (invalid plugin manager)";
|
|
// Indicate failure
|
|
return 0;
|
|
}
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
std::unique_lock<std::mutex> Lock(TraceControlMutex);
|
|
return TRM->flushAllBuffers(DeviceId);
|
|
}
|
|
|
|
// Device independent entry point for ompt_stop_trace
|
|
int libomptarget_ompt_stop_trace(int DeviceId) {
|
|
if (!PM) {
|
|
REPORT() << "Failed to stop trace for DeviceId="
|
|
<< DeviceId << " (invalid plugin manager)";
|
|
// Indicate failure
|
|
return 0;
|
|
}
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
std::unique_lock<std::mutex> Lock(TraceControlMutex);
|
|
|
|
// Schedule flushing of trace records for this device
|
|
int Status = TRM->flushAllBuffers(DeviceId);
|
|
|
|
// De-register this device so that no more traces are collected
|
|
// or delivered for this device until an ompt_start_trace is
|
|
// invoked for this device.
|
|
removeBufferManagementFns(DeviceId);
|
|
|
|
// If no device is being traced, shut down the helper threads. A
|
|
// subsequent ompt_start_trace will start up the helper threads.
|
|
if (isAllDeviceTracingStopped()) {
|
|
// TODO shutdown should perhaps return a status
|
|
TRM->shutdownHelperThreads();
|
|
llvm::omp::target::ompt::disableDeviceTracing(DeviceId);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
// Device independent entry point for ompt_advance_buffer_cursor
|
|
// Note: The input parameter size is unused here. It refers to the
|
|
// bytes returned in the corresponding callback.
|
|
int libomptarget_ompt_advance_buffer_cursor(ompt_device_t *Device,
|
|
ompt_buffer_t *Buffer, size_t Size,
|
|
ompt_buffer_cursor_t CurrentPos,
|
|
ompt_buffer_cursor_t *NextPos) {
|
|
if (!PM) {
|
|
REPORT() << "Failed to advance buffer cursor for Device="
|
|
<< Device << " (invalid plugin manager)";
|
|
// Indicate failure
|
|
return false;
|
|
}
|
|
OmptTracingBufferMgr *TRM = PM->getTraceRecordManager();
|
|
char *TraceRecord = (char *)CurrentPos;
|
|
// Don't assert if CurrentPos is null, just indicate end of buffer
|
|
if (TraceRecord == nullptr || TRM->isLastCursor(TraceRecord)) {
|
|
*NextPos = 0;
|
|
return false;
|
|
}
|
|
// TODO In debug mode, assert that the metadata points to the
|
|
// input parameter buffer
|
|
|
|
size_t TRSize = TRM->getTRSize();
|
|
*NextPos = (ompt_buffer_cursor_t)(TraceRecord + TRSize);
|
|
ODBG(ODT_Tool) << "Advanced buffer pointer by "
|
|
<< TRSize << " bytes to "
|
|
<< TraceRecord + TRSize;
|
|
return true;
|
|
}
|
|
|
|
// This function is invoked before the kernel launch. So, when the trace record
|
|
// is populated after kernel completion, TraceRecordNumGrantedTeams is already
|
|
// updated.
|
|
void libomptarget_ompt_set_granted_teams(uint32_t NumTeams) {
|
|
TraceRecordNumGrantedTeams = NumTeams;
|
|
}
|
|
|
|
// Assume a synchronous implementation and set thread local variables to track
|
|
// timestamps. The thread local variables can then be used to populate trace
|
|
// records.
|
|
void libomptarget_ompt_set_timestamp(uint64_t Start, uint64_t Stop) {
|
|
TraceRecordStartTime = Start;
|
|
TraceRecordStopTime = Stop;
|
|
}
|
|
|
|
// Device-independent entry point to query for the trace format used.
|
|
// Currently, only OMPT format is supported.
|
|
ompt_record_t
|
|
libomptarget_ompt_get_record_type(ompt_buffer_t *Buffer,
|
|
ompt_buffer_cursor_t CurrentPos) {
|
|
// TODO: When different OMPT trace buffer formats supported, this needs to be
|
|
// fixed.
|
|
return ompt_record_t::ompt_record_ompt;
|
|
}
|
|
} // extern "C"
|
|
|
|
#pragma pop_macro("DEBUG_PREFIX")
|
|
|
|
#endif // OMPT_SUPPORT
|