Skip to content

Commit f5288d3

Browse files
CI: harden Phase 1 staging + drop enhanced_vision from comparable subset
Three fixes addressing first-run CI failures on PR #14: 1. SONAME / symlink staging (MIVisionX failed with `libopenvx.so.1: cannot open shared object file`): - Replace `cp libopenvx*.so` with `find -name 'libopenvx*' -exec cp -P` so all versioned variants (libopenvx.so, libopenvx.so.1, libopenvx.so.X.Y.Z) are staged AND symlinks are preserved (so ld.so can follow the SONAME chain at load time). - Same pattern applied to MIVisionX, Khronos sample, and (defensively) anywhere else we stage native .so files. 2. Khronos sample crashes inside Tensor* kernels (segfault on TensorAdd during smoke): - Smoke + compare now use `--feature-set vision,framework` instead of `everything`. `enhanced_vision` is held back because at least one impl segfaults inside its Tensor kernels, and openvx-mark only writes its JSON at end-of-run — a mid-bench crash kills the entire signal for that vendor. Re-enable later when impl quirks are sorted upstream. 3. Failure isolation — single-impl crash should not block all signal: - Smoke step gains `continue-on-error: true` so the artifact upload (which the compare job depends on) still runs even if a specific impl crashes inside a specific kernel. - Impl artifact upload steps gain `if: always()` (defensive — same intent). - compare job's per-impl bench steps now use `if: always() && steps.detect.outputs.X == 'true'`. GitHub Actions treats any explicit `if:` without `always()` as implicit `success()`, so without this fix a crash in MIVisionX's bench would skip the Khronos and rustVX bench steps entirely and we'd lose all comparison data. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent a0268f2 commit f5288d3

1 file changed

Lines changed: 59 additions & 19 deletions

File tree

.github/workflows/ci.yml

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,13 @@ jobs:
8686
mkdir -p mivisionx-stage/lib mivisionx-stage/include
8787
LIB_SRC=$(dirname "$(find /tmp/mivisionx-install -name 'libopenvx.so' | head -1)")
8888
echo "MIVisionX libraries discovered in: $LIB_SRC"
89-
cp "$LIB_SRC"/libopenvx*.so mivisionx-stage/lib/
90-
cp "$LIB_SRC"/libvxu*.so mivisionx-stage/lib/ 2>/dev/null || true
89+
# Copy ALL libopenvx* / libvxu* entries (libopenvx.so symlink,
90+
# libopenvx.so.1 SONAME symlink, libopenvx.so.X.Y.Z real file)
91+
# preserving symlinks (-P) so ld.so can follow the SONAME chain.
92+
# Without versioned files the linker reports
93+
# "libopenvx.so.1: cannot open shared object file".
94+
find "$LIB_SRC" -maxdepth 1 -name 'libopenvx*' -exec cp -P {} mivisionx-stage/lib/ \;
95+
find "$LIB_SRC" -maxdepth 1 -name 'libvxu*' -exec cp -P {} mivisionx-stage/lib/ \;
9196
cp -r /tmp/mivisionx-install/include/mivisionx/. mivisionx-stage/include/
9297
echo "--- staged lib ---"
9398
ls -la mivisionx-stage/lib
@@ -110,16 +115,29 @@ jobs:
110115
..
111116
cmake --build . -j$(nproc)
112117
113-
- name: Run smoke benchmark (kernel + framework, VGA × 5 iters)
118+
# Smoke covers the `vision` + `framework` feature sets — i.e.
119+
# the comparison-stable subset that all three impls support
120+
# uniformly. `enhanced_vision` is excluded because at least one
121+
# impl (Khronos sample) segfaults inside Tensor* kernels, and
122+
# since openvx-mark only writes its JSON at end-of-run a mid-bench
123+
# crash takes out the entire signal. Re-enable per-impl gating
124+
# later when those impl quirks are sorted upstream.
125+
- name: Run smoke benchmark (vision + framework, VGA × 5 iters)
126+
# Smoke is advisory — if a specific impl crashes inside a
127+
# specific kernel the artifact upload (which the compare job
128+
# depends on) must still happen so vendor-vs-vendor signal
129+
# isn't lost.
130+
continue-on-error: true
114131
run: |
115-
set -euo pipefail
132+
set -eo pipefail
116133
cd build-smoke
117134
export LD_LIBRARY_PATH=${{ steps.stage.outputs.lib_dir }}:${LD_LIBRARY_PATH:-}
118-
./openvx-mark --feature-set everything \
135+
./openvx-mark --feature-set vision,framework \
119136
--resolution VGA --iterations 5 --warmup 1 \
120137
--output-dir smoke-results
121138
122139
- name: Upload MIVisionX artifact
140+
if: always()
123141
uses: actions/upload-artifact@v4
124142
with:
125143
name: impl-mivisionx
@@ -164,8 +182,10 @@ jobs:
164182
mkdir -p khronos-stage/lib khronos-stage/include
165183
LIB_SRC=$(dirname "$(find /tmp/khronos-src -name 'libopenvx.so' -not -path '*/build/*' | head -1)")
166184
echo "Khronos libraries discovered in: $LIB_SRC"
167-
cp "$LIB_SRC"/libopenvx*.so khronos-stage/lib/
168-
cp "$LIB_SRC"/libvxu*.so khronos-stage/lib/ 2>/dev/null || true
185+
# Same approach as MIVisionX: copy all libopenvx* / libvxu* entries
186+
# preserving symlinks so ld.so can follow the SONAME chain.
187+
find "$LIB_SRC" -maxdepth 1 -name 'libopenvx*' -exec cp -P {} khronos-stage/lib/ \;
188+
find "$LIB_SRC" -maxdepth 1 -name 'libvxu*' -exec cp -P {} khronos-stage/lib/ \;
169189
cp -r /tmp/khronos-src/api-docs/include/. khronos-stage/include/
170190
echo "--- staged lib ---"
171191
ls -la khronos-stage/lib
@@ -188,16 +208,20 @@ jobs:
188208
..
189209
cmake --build . -j$(nproc)
190210
191-
- name: Run smoke benchmark (kernel + framework, VGA × 5 iters)
211+
# Smoke is restricted to the `vision` + `framework` subset for
212+
# the same reason as the MIVisionX smoke — see comment there.
213+
- name: Run smoke benchmark (vision + framework, VGA × 5 iters)
214+
continue-on-error: true
192215
run: |
193-
set -euo pipefail
216+
set -eo pipefail
194217
cd build-smoke
195218
export LD_LIBRARY_PATH=${{ steps.stage.outputs.lib_dir }}:${LD_LIBRARY_PATH:-}
196-
./openvx-mark --feature-set everything \
219+
./openvx-mark --feature-set vision,framework \
197220
--resolution VGA --iterations 5 --warmup 1 \
198221
--output-dir smoke-results
199222
200223
- name: Upload Khronos sample artifact
224+
if: always()
201225
uses: actions/upload-artifact@v4
202226
with:
203227
name: impl-khronos-sample
@@ -314,16 +338,20 @@ jobs:
314338
..
315339
cmake --build . -j$(nproc)
316340
317-
- name: Run smoke benchmark (kernel + framework, VGA × 5 iters)
341+
# Smoke is restricted to the `vision` + `framework` subset for
342+
# the same reason as the MIVisionX smoke — see comment there.
343+
- name: Run smoke benchmark (vision + framework, VGA × 5 iters)
344+
continue-on-error: true
318345
run: |
319-
set -euo pipefail
346+
set -eo pipefail
320347
cd build-smoke
321348
export LD_LIBRARY_PATH=${{ steps.stage.outputs.lib_dir }}:${LD_LIBRARY_PATH:-}
322-
./openvx-mark --feature-set everything \
349+
./openvx-mark --feature-set vision,framework \
323350
--resolution VGA --iterations 5 --warmup 1 \
324351
--output-dir smoke-results
325352
326353
- name: Upload rustVX artifact
354+
if: always()
327355
uses: actions/upload-artifact@v4
328356
with:
329357
name: impl-rustvx
@@ -407,8 +435,20 @@ jobs:
407435
done
408436
409437
# ----- Per-impl build + benchmark (FHD, 20 iter, 5 warmup) -----
438+
#
439+
# Each per-impl bench uses `if: always() && steps.detect...` because
440+
# GitHub Actions treats any explicit `if:` without `always()` as
441+
# implicit `success()` — meaning a crash in MIVisionX bench would
442+
# skip the Khronos / rustVX bench steps entirely and we'd lose all
443+
# comparison signal. With `always()` the three benches stay
444+
# independent and the comparison job downstream handles whichever
445+
# JSON files actually got produced.
446+
#
447+
# Feature set is `vision,framework` (the comparison-stable subset
448+
# — see the smoke step comments for why `enhanced_vision` is held
449+
# back for now).
410450
- name: Build & bench against MIVisionX
411-
if: steps.detect.outputs.mivisionx == 'true'
451+
if: always() && steps.detect.outputs.mivisionx == 'true'
412452
run: |
413453
set -euo pipefail
414454
mkdir -p build-mivisionx
@@ -420,12 +460,12 @@ jobs:
420460
..
421461
cmake --build . -j$(nproc)
422462
export LD_LIBRARY_PATH=${{ github.workspace }}/impl/mivisionx/lib:${LD_LIBRARY_PATH:-}
423-
./openvx-mark --feature-set everything \
463+
./openvx-mark --feature-set vision,framework \
424464
--resolution FHD --iterations 20 --warmup 5 \
425465
--output-dir results
426466
427467
- name: Build & bench against Khronos sample
428-
if: steps.detect.outputs.khronos == 'true'
468+
if: always() && steps.detect.outputs.khronos == 'true'
429469
run: |
430470
set -euo pipefail
431471
mkdir -p build-khronos
@@ -437,12 +477,12 @@ jobs:
437477
..
438478
cmake --build . -j$(nproc)
439479
export LD_LIBRARY_PATH=${{ github.workspace }}/impl/khronos/lib:${LD_LIBRARY_PATH:-}
440-
./openvx-mark --feature-set everything \
480+
./openvx-mark --feature-set vision,framework \
441481
--resolution FHD --iterations 20 --warmup 5 \
442482
--output-dir results
443483
444484
- name: Build & bench against rustVX
445-
if: steps.detect.outputs.rustvx == 'true'
485+
if: always() && steps.detect.outputs.rustvx == 'true'
446486
run: |
447487
set -euo pipefail
448488
mkdir -p build-rustvx
@@ -454,7 +494,7 @@ jobs:
454494
..
455495
cmake --build . -j$(nproc)
456496
export LD_LIBRARY_PATH=${{ github.workspace }}/impl/rustvx/lib:${LD_LIBRARY_PATH:-}
457-
./openvx-mark --feature-set everything \
497+
./openvx-mark --feature-set vision,framework \
458498
--resolution FHD --iterations 20 --warmup 5 \
459499
--output-dir results
460500

0 commit comments

Comments
 (0)