Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions libkineto/src/plugin/xpupti/XpuptiActivityHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,7 @@ void XpuptiActivityProfilerSession::handleRuntimeKernelMemcpyMemsetActivities(
if constexpr (handleRuntimeActivities) {
trace_activity->device = activity->_process_id;
trace_activity->resource = activity->_thread_id;
trace_activity->flow.start =
(correlateRuntimeOps_.count(trace_activity->name()) > 0);
trace_activity->flow.start = startsFlow(activityType);
} else {
trace_activity->device = getDeviceIdxFromUUID(activity->_device_uuid);
trace_activity->resource = activity->_sycl_queue_id;
Expand Down
29 changes: 9 additions & 20 deletions libkineto/src/plugin/xpupti/XpuptiActivityProfilerSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,17 @@

namespace KINETO_NAMESPACE {

using namespace std::literals::string_view_literals;

uint32_t XpuptiActivityProfilerSession::iterationCount_ = 0;
std::vector<DeviceUUIDsT> XpuptiActivityProfilerSession::deviceUUIDs_ = {};
std::unordered_set<std::string_view>
XpuptiActivityProfilerSession::correlateRuntimeOps_ = {
"piextUSMEnqueueFill"sv,
"urEnqueueUSMFill"sv,
"piextUSMEnqueueFill2D"sv,
"urEnqueueUSMFill2D"sv,
"piextUSMEnqueueMemcpy"sv,
"urEnqueueUSMMemcpy"sv,
"piextUSMEnqueueMemset"sv,
"piextUSMEnqueueMemcpy2D"sv,
"urEnqueueUSMMemcpy2D"sv,
"piextUSMEnqueueMemset2D"sv,
"piEnqueueKernelLaunch"sv,
"urEnqueueKernelLaunch"sv,
"piextEnqueueKernelLaunchCustom"sv,
"urEnqueueKernelLaunchCustomExp"sv,
"piextEnqueueCooperativeKernelLaunch"sv,
"urEnqueueCooperativeKernelLaunchExp"sv};

bool XpuptiActivityProfilerSession::startsFlow(ActivityType activityType) {
// Only host runtime records start the CPU->GPU flow. The runtime view is
// already filtered to work-submitting APIs via
// ptiViewEnableRuntimeApiClass(PTI_API_CLASS_GPU_OPERATION_CORE). Driver
// (XPU_DRIVER) records share the same correlation id as the runtime record
// and must not also start a flow, or the trace gets a duplicate flow start.
return activityType == ActivityType::XPU_RUNTIME;
}

// =========== Session Constructor ============= //
XpuptiActivityProfilerSession::XpuptiActivityProfilerSession(
Expand Down
8 changes: 6 additions & 2 deletions libkineto/src/plugin/xpupti/XpuptiActivityProfilerSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <memory>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace KINETO_NAMESPACE {
Expand Down Expand Up @@ -61,6 +60,12 @@ class XpuptiActivityProfilerSession : public libkineto::IActivityProfilerSession
void pushUserCorrelationId(uint64_t id) override;
void popUserCorrelationId() override;

// Whether a runtime/driver record starts a CPU->GPU flow arrow. Only host
// runtime (XPU_RUNTIME) records do; driver (XPU_DRIVER) records share the
// same correlation id and would otherwise create a duplicate flow start.
// Static so it can be unit-tested without real hardware.
static bool startsFlow(ActivityType activityType);

private:
void checkTimestampOrder(const ITraceActivity* act1);
void removeCorrelatedPtiActivities(const ITraceActivity* act1);
Expand Down Expand Up @@ -94,7 +99,6 @@ class XpuptiActivityProfilerSession : public libkineto::IActivityProfilerSession
protected:
static uint32_t iterationCount_;
static std::vector<DeviceUUIDsT> deviceUUIDs_;
static std::unordered_set<std::string_view> correlateRuntimeOps_;

int64_t captureWindowStartTime_{0};
int64_t captureWindowEndTime_{0};
Expand Down
5 changes: 5 additions & 0 deletions libkineto/test/xpupti/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ add_executable(XpuptiScopeProfilerConfigTest XpuptiScopeProfilerConfigTest.cpp)
target_link_libraries(XpuptiScopeProfilerConfigTest PRIVATE ${LINK_LIBRARIES})
gtest_discover_tests(XpuptiScopeProfilerConfigTest)

# Hardware-free test for the CPU->GPU flow-link allowlist.
add_executable(XpuptiFlowCorrelationTest XpuptiFlowCorrelationTest.cpp)
target_link_libraries(XpuptiFlowCorrelationTest PRIVATE ${LINK_LIBRARIES})
gtest_discover_tests(XpuptiFlowCorrelationTest)

include(ExternalProject)

function(make_test test_file)
Expand Down
41 changes: 41 additions & 0 deletions libkineto/test/xpupti/XpuptiFlowCorrelationTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//==============================================================
// Copyright (C) Intel Corporation
//
// SPDX-License-Identifier: MIT
// =============================================================

#include "src/plugin/xpupti/XpuptiActivityProfilerSession.h"

#include <gtest/gtest.h>

namespace KN = KINETO_NAMESPACE;

// Exercises the predicate that decides which records start a CPU->GPU ("ac2g")
// flow arrow. Runs without a GPU: only the static predicate is queried, no PTI
// collection is performed.

TEST(XpuptiFlowCorrelationTest, RuntimeRecordsStartFlow) {
// Host runtime records (kernel launches, memcpy/fill enqueues) are the source
// of the CPU->GPU arrow. The runtime view is filtered to work-submitting APIs
// by ptiViewEnableRuntimeApiClass(PTI_API_CLASS_GPU_OPERATION_CORE).
EXPECT_TRUE(KN::XpuptiActivityProfilerSession::startsFlow(
KN::ActivityType::XPU_RUNTIME));
}

TEST(XpuptiFlowCorrelationTest, DriverRecordsDoNotStartFlow) {
// Driver (ze*) records share the runtime record's correlation id; if they
// also started a flow the trace would have a duplicate flow start for that
// id (Perfetto flow_duplicate_id). They must only be flow ends.
EXPECT_FALSE(KN::XpuptiActivityProfilerSession::startsFlow(
KN::ActivityType::XPU_DRIVER));
}

TEST(XpuptiFlowCorrelationTest, DeviceRecordsDoNotStartFlow) {
// GPU-side activities are flow destinations, never sources.
EXPECT_FALSE(KN::XpuptiActivityProfilerSession::startsFlow(
KN::ActivityType::CONCURRENT_KERNEL));
EXPECT_FALSE(KN::XpuptiActivityProfilerSession::startsFlow(
KN::ActivityType::GPU_MEMCPY));
EXPECT_FALSE(KN::XpuptiActivityProfilerSession::startsFlow(
KN::ActivityType::GPU_MEMSET));
}
Loading