Skip to content

samples: add OpenVX graph pipelining CPU+GPU sample - #7

Open
simonCatBot wants to merge 10 commits into
developfrom
feature/pipelining-sample
Open

samples: add OpenVX graph pipelining CPU+GPU sample#7
simonCatBot wants to merge 10 commits into
developfrom
feature/pipelining-sample

Conversation

@simonCatBot

Copy link
Copy Markdown
Owner

Summary

Adds a new C++ sample under samples/c_samples/pipelining that demonstrates the OpenVX vx_khr_pipelining extension on a mixed CPU+GPU workload.

The sample runs the same vision graph in two modes:

  • --pipeline 0 — synchronous vxProcessGraph loop (baseline).
  • --pipeline 1QUEUE_AUTO pipelined enqueue/dequeue with multiple input/output buffers.

Graph: RGB -> ColorConvert -> ChannelExtract(Y) -> Box3x3 -> U8

Both paths compute an identical per-frame checksum aggregate, and the pipelined path reports a higher fps so the benefit is immediately visible.

What was added

  • samples/c_samples/pipelining/pipelining.cpp — the sample application.
  • samples/c_samples/pipelining/CMakeLists.txt — build file matching the existing canny sample.
  • Updated samples/c_samples/README.md with build/run instructions.

Verification performed

Built and tested locally on a Radeon gfx1151 GPU and on the CPU-only backend:

Mode Backend fps (60 frames @ 640x480) checksum aggregate
sync HIP ~447 2309715656
pipe HIP ~503 2309715656
sync CPU ~352 2304694854
pipe CPU ~531 2304694854

Both backends pass the checksum-equality test and show measurable speed-up when pipelining is enabled.

Checklist

  • Builds on HIP backend.
  • Builds on CPU-only backend.
  • --pipeline 0 and --pipeline 1 produce the same aggregate checksum.
  • --pipeline 1 reports higher fps than --pipeline 0.
  • Does not touch any existing library code; only adds a new sample.

@simonCatBot
simonCatBot force-pushed the feature/pipelining-sample branch from 8b51ead to ab8c164 Compare August 6, 2026 17:38
@daniellegillai

Copy link
Copy Markdown

Tested on Radeon RX 9070 XT / Ryzen 9 9950X 16-Core Processor, using TheRock Nightly 10.1.0 2026-08-05:

Mode Backend fps (60 frames @ 640x480) checksum aggregate
sync HIP ~422 2309715656
pipe HIP ~456 2309715656
sync CPU ~450 2304694854
pipe CPU ~498 2304694854

Both backends pass the checksum-equality test and show speed-up when pipelining is enabled. One note is that CPU outperformed HIP backend, @kiritigowda is that reasonable?

@simonCatBot
simonCatBot force-pushed the feature/pipelining-sample branch 3 times, most recently from 4b11c3c to 00322f5 Compare August 6, 2026 22:06
Add samples/c_samples/pipelining, a self-contained demonstration of the
vx_khr_pipelining extension on a mixed CPU+GPU workload. The same vision
graph (RGB -> ColorConvert -> ChannelExtract(Y) -> Box3x3 -> U8) is run
synchronously with vxProcessGraph (--pipeline 0) and asynchronously with
QUEUE_AUTO enqueue/dequeue (--pipeline 1).

Both paths report identical per-frame checksums so correctness can be
verified, while the pipelined path prints a higher fps to make the
performance benefit visible.

Also update samples/c_samples/README.md with build/run instructions.
@simonCatBot
simonCatBot force-pushed the feature/pipelining-sample branch from 00322f5 to 7f75313 Compare August 6, 2026 23:30
simonCatBot and others added 9 commits August 7, 2026 16:02
… to fix non-deterministic HIP pipe checksums

The heavy preset previously chained two GPU Box3x3 nodes through a shared
virtual intermediate. In QUEUE_AUTO pipelined mode on the HIP backend this
produced slightly different aggregate checksums on every run, while sync and
the CPU backend were stable.

Replace the heavy graph with a single Gaussian3x3 node. It keeps the preset
compute-heavy enough to show pipelining speed-up, and the sync and pipelined
paths now produce identical, deterministic checksums on both HIP and CPU
backends. The README is updated to describe the new heavy graph and to remove
the caveat about sync/pipe checksum differences.
… preset change

- Update pipelining --help to describe the heavy preset as Gaussian3x3
  instead of the old Box3x3 -> Box3x3 chain.
- Remove the misleading compare-mode message that claimed heavy sync/pipe
  checksum differences were expected.
- Fix pipelining_hybrid header comment: the CPU stage is Threshold (U8)
  -> Box3x3, not a U1 conversion.
- README: mention both Box3x3 and Gaussian3x3 as the heavier convolutions.
These GDF files demonstrate the proposed GDF syntax for vx_khr_pipelining
support in runvx. They are not executable today because runvx does not yet
implement QUEUE_AUTO, graph parameters, or enqueue/dequeue primitives.

Files:
- utilities/runvx/gdf/pipelining/README.md
- utilities/runvx/gdf/pipelining/pipelining_box3x3.gdf
- utilities/runvx/gdf/pipelining/pipelining_gaussian3x3.gdf
- utilities/runvx/gdf/pipelining/pipelining_hybrid.gdf

See ROCm#1734 for the enhancement request.
…EUE_MANUAL over-scheduling in graph pipelining (ROCm#1729)

* Fix cross-target hand-off, queued OpenCL args, and QUEUE_MANUAL over-scheduling

Three defects kept a pipelined graph from being usable once its work was
split across the CPU and the GPU.

A CPU node only recorded that it had written a buffer when that buffer
already had device memory. A graph that hands its output to another graph
usually writes an image no GPU node has bound yet, so the record was
skipped, and the device memory reserved later by the consuming graph was
read without ever being uploaded. The CPU node now records the write
regardless, and a device buffer reserved for a queued reference starts out
needing an upload.

On OpenCL, buffer kernel arguments are bound when the graph is verified.
That holds for an object that stays put, and the code already re-bound
delay slots, but a queued graph parameter names a different reference on
every execution. Every execution after the first therefore wrote the
reference chosen at verification time. Queued references are now re-bound
the same way delay slots are.

In QUEUE_MANUAL, vxScheduleGraph runs every complete set of enqueued
references it finds rather than a single one, so a request could carry out
work that later requests were made for; those requests then found empty
queues and reported an error for work that had in fact been done. The
extra executions are credited and spent by the requests that follow, which
keeps the error for the case it was written for - an application that
scheduled the graph without enqueueing a reference everywhere.

Two tests cover the parts that were silently wrong: a two-graph GPU-after-
CPU chain whose result is only exact if the hand-off uploads, and a
QUEUE_MANUAL run that checks each enqueued set runs once, with correct
data and no failure logged.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Make the QUEUE_MANUAL execution accounting explicit

Review pointed out that crediting the executions a request performs beyond
the one it asked for leaves credits behind that nothing is waiting for, so
a later request with empty queues reports success instead of the missing
references.

A request cannot be limited to a single execution instead. The conformance
suite's GraphPipeline.testManualSchedule enqueues one set per buffer,
schedules the graph once, and requires every one of those sets to have run
by the time it dequeues; one execution per request fails 7 of the 109
pipelining tests.

With the number of executions decoupled from the number of requests that
way, an application that enqueues N sets and schedules once and then N-1
times, and one that enqueues and schedules N times where a request ran
several sets, make exactly the same calls in the same order. Nothing in the
queues separates them, so what separates a request whose work an earlier
one already did from a request the application enqueued nothing for is
whether an execution is there to claim. The counter now says that directly:
every request claims one execution, the executions no request has claimed
are carried, and reconfiguring the graph starts the count again.

Test 27 now covers both directions, a request per enqueued set and one
request for every enqueued set, and checks that a request with nothing
enqueued for it is still reported as an error.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants