[xpupti] Don't emit ac2g flow endpoints on XPU_DRIVER records - #1549
ryanzhang22 merged 15 commits into
Conversation
The SYCL runtime record, the Level Zero driver (ze*) record and the device kernel share one correlation id, and handleRuntimeKernelMemcpyMemsetActivities sets flow.id/flow.type on all of them. The driver record then becomes an extra ac2g flow endpoint, so Perfetto draws a redundant host->host arrow from the runtime "submit" slice to its nested ze* child; non-launch ze* calls (which get fresh correlation ids) also emit dangling flow finishes with no matching start. Gate the flow assignment on a new carriesFlow() predicate so only the runtime (flow source) and the device activities (kernel/memcpy/memset, flow destination) carry the ac2g flow; XPU_DRIVER records carry none. Add predicate unit tests and a handler-level test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@pytorchbot label 'ciflow/xpu' |
|
The ciflow label(s) ciflow/xpu will be added, but CI won't be triggered until the workflows are approved (scroll to the bottom of this page). Please ping one of the reviewers if you do not have access to approve and run workflows. |
|
|
|
@guangyey, @gujinghui, @EikanWang please review |
Review feedback on pytorch#1549: `carriesFlow` claimed to test whether a record is a "CPU->GPU flow endpoint", yet returned true for XPU_RUNTIME -- the host side, which is the flow *source*, not its destination. The name also did not say which of the two flow types (fwdbwd, ac2g) it meant. Replace `startsFlow` and `carriesFlow` with a single `ac2gFlowRole()` returning {None, Source, Destination}: the flow type is named in the predicate, `Source`/`Destination` replaces the ambiguous "endpoint", and one list of activity types can no longer drift out of sync with a second one -- flow id, type and start are now set together in one place. Scoping the name to ac2g is accurate rather than provisional: the plugin never emits fwdbwd, which the PyTorch CPU-side profiler generates and no device backend sees. Both predicates were public static members only so the unit test could reach them, and a test that re-asserts the switch's own table proves little. Drop XpuptiFlowCorrelationTest, move the function into an anonymous namespace in the only translation unit that uses it, and assert the observable behaviour in XpuptiActivityHandlersTest instead: memcpy and memset records are flow destinations, and the driver record's flow *type* stays 0 along with its id (an id with type 0 reaches handleGenericLink, which then logs "Unknown flow type" for every such record).
…o-driver-flow-arrows
An activity selection that keeps XPU_DRIVER but drops XPU_RUNTIME lost every CPU->GPU arrow, as only a runtime record could start a flow. Let the driver record take that role when the runtime view is absent; it shares the device work's correlation id. While both views are collected the driver record stays out of the flow: an arrow to a span nested under the submit would run host->host. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…o-driver-flow-arrows # Conflicts: # libkineto/src/plugin/xpupti/XpuptiActivityProfilerSession.h # libkineto/test/xpupti/XpuptiActivityHandlersTest.cpp
…iver-flow-arrows' into dev/adrianos/xpupti-no-driver-flow-arrows # Conflicts: # libkineto/src/plugin/xpupti/XpuptiActivityHandlers.cpp
The session borrowed a reference into a ConfigDerivedState that kineto rebuilds on every configure(), and it now also derives a bitmask from that set. Copying it removes both the dangling-reference window and the second representation that could drift from the first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…o-driver-flow-arrows
The ac2g comment now says what the function decides instead of how the records nest, and stays with the XPU_RUNTIME/XPU_DRIVER names the rest of Kineto uses. The mask's default constructor had no caller, and the local enum has no reason to fix its underlying type. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The session held the selection twice: the caller's set and a bitmask derived from it, which could drift apart. Our own enable/disable API now takes the mask, so the session keeps only that. The selection is fixed for a session's lifetime, since kineto clears its sessions before it rebuilds the config state on the next configure(). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An unconstrained template parameter accepts anything and reports the mismatch from deep inside the body; std::invocable states the expected signature at the boundary, where the caller sees it. Kineto already uses this form in TypedMetadata.h. The visiting order is now part of the contract, so tests cover it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@ryanzhang22 @scotts please review |
|
@ryanzhang22 @scotts can you take a look? The unrelated CI failure should not block this PR from being merged. |
|
Sorry was out on vacation for a few days. Will take a look. |
| 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 |
There was a problem hiding this comment.
In XPU, is there an expectation that all driver calls produce a kernel event? I see that PTI_API_CLASS_GPU_OPERATION_CORE is used for filtering of runtime events, do you need the same thing for driver events?
JFYI for CUDA jobs we check if we need a flow arrow on the API call level: https://github.com/pytorch/kineto/blob/main/libkineto/src/CuptiCbidRegistry.cpp#L87
This lets us filter out individual calls (but we don't do the runtime -> driver fallback).
There was a problem hiding this comment.
Not all driver calls produce kernels, but once we have filtering in place #1570 virtually all of them will (except barriers, I think).
The user might still want to filter out driver events.
The driver record's role depends on whether the runtime view is traced, which a free function could only learn through a bool argument set at the call site -- far from the one case that reads it. As a member of the session that owns the activity selection, it consults that selection in the XPU_DRIVER branch itself. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Enabling and disabling the views repeated the same list of activity types, so a type added to one could be missed in the other. A single mapping now answers which view a type is collected through, leaving enable with just the extras a view needs on top. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@aostrowski-hbn Could you guys take a look at the XPU CI failure? Seems like it's happening on other PRs too. |
Last one! Includes the following commits: - [Kineto] Exclude test on windows (pytorch/kineto#1575) 638a3ef - Opt-in per-thread activity buffers on the ROCm HIP path (pytorch/kineto#1573) 5dc9333 - Parse DISABLE_CUPTI_LAZY_REINIT by value (pytorch/kineto#1568) f140a13 - [Kineto] Add lookback window and sampling interval as config options (pytorch/kineto#1561) fcda441 - [xpupti] Don't emit ac2g flow endpoints on XPU_DRIVER records (pytorch/kineto#1549) f0df071 Pull Request resolved: #198560 Approved by: https://github.com/sanrise Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
What
Stop the XPU (xpupti) profiler plugin from attaching a CPU→GPU ("ac2g") flow
endpoint to
XPU_DRIVER(Level Zeroze*) records.Why
The SYCL runtime record, the Level Zero driver (
ze*) record and the devicekernel all share one PTI correlation id, and
handleRuntimeKernelMemcpyMemsetActivitiessetflow.id/flow.typeon all ofthem — so the driver record became an extra ac2g flow endpoint. In the exported
Chrome/Perfetto trace this draws a redundant host→host arrow from the
runtime "submit" slice to its own nested
ze*child (already its child on thesame track), and the non-launch
ze*calls — which get fresh correlation ids —emit dangling flow finishes with no matching start.
ac2gmeans asyncCPU→GPU: a flow should link a host launch to the device op, never both start
and end on the host.
How
A single
ac2gFlowRole()helper maps the record's activity type to{None, Source, Destination}, andflow.id,flow.typeandflow.startareset together from it. The host runtime record is the
Source, kernel / memcpy /memset are
Destinations, andXPU_DRIVERrecords getNone— so their flowid stays 0 and
output_json'sflowId() > 0guard emits no link. Theze*slices themselves stay in the trace; only their redundant arrows go.
Naming the flow type in the predicate is deliberate rather than provisional:
ac2gis the only flow this plugin can emit —fwdbwdlinks are generated bythe PyTorch CPU-side profiler (
generateForwardBackwardLink) from autogradsequence numbers and never reach a device backend.
Source/Destinationalsosays which end a record is, which the reviewed
carriesFlowname did not.Folding the two predicates (
startsFlow+carriesFlow) into one removes asecond list of activity types that could drift out of sync with the first.
Test
XpuptiActivityHandlersTestasserts the observable flow fields on hand-builtPTI records rather than re-asserting the predicate's own table: the runtime
record is a flow start, kernel / memcpy / memset are flow ends, and the
XPU_DRIVERrecord carries neither a flow id nor a flow type — an id withtype 0 would reach
handleGenericLink, which then logs "Unknown flow type" forevery such record.
Built and the full xpupti ctest suite run on Intel GPU hardware (Intel® Arc™
Pro B-Series Graphics and Intel Data Center GPU Max Series); this revision was
re-verified on Intel Data Center GPU Max Series against PTI 1.2.0 — 22/22 pass
(
XpuptiScopeProfilerTest.PerKernelScopeis skipped upstream, #1533).Before/after Perfetto traces confirm the redundant driver arrows drop to zero
while the runtime→kernel arrows are unchanged.
A companion PyTorch profiler test (kept in draft until this lands) guards the
same property end-to-end.
Companion (draft): pytorch/pytorch#194904