Skip to content

Commit c1fd84b

Browse files
[Tutorial] [O2AT6] Potential tutorial task for GPU execution of neural networks (#18471)
Co-authored-by: ALICE Action Bot <alibuild@cern.ch>
1 parent de6550e commit c1fd84b

3 files changed

Lines changed: 400 additions & 0 deletions

File tree

‎Tutorials/ML/CMakeLists.txt‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,14 @@ o2physics_add_dpl_workflow(apply-ml-selection
1919
SOURCES applyMlSelection.cxx
2020
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore
2121
COMPONENT_NAME AnalysisTutorial)
22+
23+
o2physics_add_dpl_workflow(benchmark-onnx-model
24+
SOURCES benchmarkOnnxModel.cxx
25+
PUBLIC_LINK_LIBRARIES O2::Framework O2::ML O2::GPUCommon ONNXRuntime::ONNXRuntime
26+
TARGETVARNAME benchmarkOnnxModelTarget
27+
COMPONENT_NAME AnalysisTutorial)
28+
29+
# System libraries are linked directly: the workflow helper requires namespaced targets.
30+
if(CMAKE_DL_LIBS)
31+
target_link_libraries(${benchmarkOnnxModelTarget} PRIVATE ${CMAKE_DL_LIBS})
32+
endif()

‎Tutorials/ML/README-benchmark.md‎

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# ONNX inference benchmark tutorial
2+
3+
`benchmarkOnnxModel.cxx` registers `o2-analysis-benchmark-onnx-model`.
4+
It runs once with deterministic synthetic data, writes one CSV row, and exits.
5+
It accepts one dense floating-point input of shape `[batch, features]` and one
6+
or more outputs. Static dimensions must match the options; symbolic dimensions
7+
are filled from the options. Output types are left to ONNX Runtime.
8+
9+
## Build and GPU prerequisites
10+
11+
Build O2Physics normally after loading its O2 environment. This target links
12+
`O2::ML`, `O2::GPUCommon`, `ONNXRuntime::ONNXRuntime`, and the platform dynamic
13+
loader. No HIP or CUDA headers are required for building the task. The O2 installation
14+
must contain `ML/3rdparty/GPUORTFloat16.h` and its GPUCommon headers.
15+
16+
For AMD GPU runs, ONNX Runtime must contain **MIGraphXExecutionProvider**, and its
17+
MIGraphX/ROCm shared libraries, including `libamdhip64.so`, must be discoverable
18+
at runtime. The task checks provider availability and disables CPU fallback:
19+
unsupported graphs fail rather than producing a misleading GPU benchmark.
20+
No changes to O2's OrtInterface are needed for this task; the current checked-out
21+
OrtInterface does not attach an AMD execution provider, so this example uses
22+
ORT directly.
23+
24+
For NVIDIA runs, select `--provider cuda`. ONNX Runtime must contain
25+
**CUDAExecutionProvider**, with matching CUDA/cuDNN libraries and an NVIDIA
26+
driver. Telemetry loads `libcudart.so` (also tries `.so.13`, `.so.12`, `.so.11.0`)
27+
from the library search path. Keep this runtime consistent with the ORT CUDA
28+
build. CUDA provider options require ORT 1.18 or newer: `use_tf32=0` disables
29+
TF32 so the FP32 benchmark does not silently use TF32 matrix multiplication.
30+
Both GPU backends disable CPU fallback and use the same timing/CSV path.
31+
32+
Check the actual hydra driver, ROCm, MIGraphX and ORT combination first. MI100
33+
(gfx908) and MI50 (gfx906) do not have identical software support. MI50 is absent
34+
from current supported ROCm hardware lists, so it needs a compatible older
35+
stack or a separately validated build. The old ROCm execution provider was
36+
removed from ONNX Runtime starting with 1.23; this task uses MIGraphX.
37+
38+
References:
39+
- <https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html>
40+
- <https://onnxruntime.ai/docs/execution-providers/MIGraphX-ExecutionProvider.html>
41+
- <https://onnxruntime.ai/docs/execution-providers/ROCm-ExecutionProvider.html>
42+
- <https://rocm.docs.amd.com/projects/install-on-linux/en/latest/reference/system-requirements.html>
43+
44+
## Run the three comparisons
45+
46+
Use equivalent FP32 and FP16 exports of the same network. Replace the example
47+
feature count with the actual model input width. Use separate output files;
48+
each invocation overwrites its output CSV.
49+
50+
```bash
51+
o2-analysis-benchmark-onnx-model -b --model-path model-fp32.onnx \
52+
--provider cpu --fp16 false --batch-size 1024 --features 5 \
53+
--cpu-threads 1 --warmup 20 --iterations 200 --output-csv cpu-fp32.csv
54+
55+
o2-analysis-benchmark-onnx-model -b --model-path model-fp32.onnx \
56+
--provider migraphx --gpu-id 0 --fp16 false --batch-size 1024 --features 5 \
57+
--warmup 20 --iterations 200 --output-csv gpu-fp32.csv
58+
59+
o2-analysis-benchmark-onnx-model -b --model-path model-fp16.onnx \
60+
--provider migraphx --gpu-id 0 --fp16 true --batch-size 1024 --features 5 \
61+
--warmup 20 --iterations 200 --output-csv gpu-fp16.csv
62+
```
63+
64+
For NVIDIA, replace `--provider migraphx` with `--provider cuda`, for example:
65+
66+
```bash
67+
o2-analysis-benchmark-onnx-model -b --model-path model-fp32.onnx \
68+
--provider cuda --gpu-id 0 --fp16 false --batch-size 1024 --features 5 \
69+
--warmup 20 --iterations 200 --output-csv cuda-fp32.csv
70+
71+
o2-analysis-benchmark-onnx-model -b --model-path model-fp16.onnx \
72+
--provider cuda --gpu-id 0 --fp16 true --batch-size 1024 --features 5 \
73+
--warmup 20 --iterations 200 --output-csv cuda-fp16.csv
74+
```
75+
76+
`gpu-id` is the logical ID after `HIP_VISIBLE_DEVICES` / `ROCR_VISIBLE_DEVICES`
77+
masking on AMD or `CUDA_VISIBLE_DEVICES` masking on NVIDIA. Run one benchmark process at a time on an idle
78+
GPU. Repeat with the same batch sizes and CPU thread count, and compare several
79+
runs. Small batches can be dominated by host overhead and transfers.
80+
81+
`--fp16 true` selects O2's `o2::OrtDataType::Float16_t` input storage and checks
82+
that the model input is FLOAT16. It does not convert model weights or prove that
83+
every internal operation is FP16. Export/inspect the model accordingly. FP16
84+
models retaining FP32 input interfaces need an adapted input path; this small
85+
tutorial intentionally rejects them. CPU runs require FP32 input.
86+
87+
## What the CSV measures
88+
89+
- `samples_per_second = batch_size * iterations / seconds`.
90+
- Timing covers synchronous `Session::Run`, input/output transfers, and output
91+
allocation/destruction. It excludes session creation, MIGraphX compilation,
92+
warmup, input generation, FP16 conversion, telemetry, and CSV I/O. This is
93+
host-to-host inference throughput, not GPU kernel-only throughput.
94+
- GPU memory fields are **device-wide used bytes**, sampled through
95+
`hipMemGetInfo` (AMD) or `cudaMemGetInfo` (NVIDIA) before session creation, after warmup, and after timed runs.
96+
They include other processes and runtime allocations; they are neither
97+
model-only memory nor a transient peak. The baseline follows GPU runtime/context
98+
initialization. CPU runs leave these fields empty. GPU telemetry failures
99+
fail the run rather than reporting zero usage.
100+
- Precision labels describe the requested model/input variant, not measured
101+
arithmetic precision. Strict CPU fallback rejection can reject graphs that
102+
would otherwise run with some CPU operators.
103+
104+
This benchmark does not check prediction accuracy. Compare real model outputs
105+
between the exports separately before interpreting performance gains.
106+
107+
## Adding the AO2D input later
108+
109+
Planned input on hydra:
110+
111+
```text
112+
/lustre/alice/users/marin/R3A/TPCTrees/TPCTrees_LHC24as_250224/AO2D_merge_LHC24as_updatedBB_250224.root
113+
```
114+
115+
The file has not been inspected here. Do not pass `--aod-file` to this standalone
116+
synthetic task yet. First establish the AO2D tables, feature columns and order,
117+
training normalization, selections, and missing-value policy. Then add an
118+
analysis `process(...)` input with the appropriate table definitions, build
119+
contiguous batches from its rows, and reuse the inference path. Keep session
120+
creation in `init`, aggregate timing/sample counts across batches, and write
121+
results at end of stream. Handle the final partial batch explicitly (dynamic
122+
batch, or pad and count only valid samples). Keep data reading/preprocessing
123+
outside inference timing or report a separate full-pipeline metric.

0 commit comments

Comments
 (0)