-
Notifications
You must be signed in to change notification settings - Fork 0
367 lines (341 loc) · 18.1 KB
/
Copy pathci.yml
File metadata and controls
367 lines (341 loc) · 18.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# CI design is minute-budget-conscious (see docs/ENVIRONMENT.md "CI" section):
# - One Linux job sweeps all x86 tiers sequentially: Highway builds once,
# only corvus rebuilds per cap. A matrix would multiply job setup and
# Highway builds for the same information.
# - Sanitizers run inside the same Linux job (one extra Debug build).
# - One macOS arm64 job: the expensive runner class, but the only one
# producing new data (native NEON silicon).
# - One Windows job for TOOLCHAIN coverage, not tier coverage: MSVC is the
# only compiler in the fleet that can produce Windows-specific diagnostics,
# and the VS generator is the only multi-config generator we build under.
# - Docs-only changes skip CI entirely.
name: CI
on:
push:
branches: [main]
paths-ignore: ['**.md', 'docs/**', 'LICENSE']
pull_request:
paths-ignore: ['**.md', 'docs/**', 'LICENSE']
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
linux-x86:
name: Linux x86-64 (tier sweep + sanitizers)
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Every tier is capped explicitly and the reached target is ASSERTED via
# CORVUS_EXPECT_TARGET — hosted runner ISA is not guaranteed (some are
# AVX-512-capable), so an uncapped run would silently test whatever
# silicon it drew and skip the tier it claims. AVX10_2 belongs in BASE
# even though HWY_BROKEN_AVX10_2 currently blocks it: that block is
# version-gated on the toolchain and will expire, unlike this cap.
- name: Tier sweep (AVX2, SSE4, SSSE3, SSE2)
run: |
BASE="HWY_AVX10_2|HWY_AVX3_SPR|HWY_AVX3_ZEN4|HWY_AVX3_DL|HWY_AVX3"
for TIER in AVX2 SSE4 SSSE3 SSE2; do
case $TIER in
AVX2) CAP="$BASE" ;;
SSE4) CAP="$BASE|HWY_AVX2" ;;
SSSE3) CAP="$BASE|HWY_AVX2|HWY_SSE4" ;;
SSE2) CAP="$BASE|HWY_AVX2|HWY_SSE4|HWY_SSSE3" ;;
esac
echo "::group::$TIER (CORVUS_DISABLED_TARGETS=$CAP)"
cmake -B build -G Ninja -DCORVUS_WERROR=ON \
-DCORVUS_DISABLED_TARGETS="$CAP"
cmake --build build
CORVUS_EXPECT_TARGET="$TIER" \
ctest --test-dir build --output-on-failure
echo "::endgroup::"
done
# ctest hides output on success; log the measured numbers. Capped to AVX2
# rather than left uncapped (the last sweep iteration leaves SSE-capped
# binaries, so this must reconfigure anyway) — the report has to name the
# tier it measured, which means pinning it rather than inheriting the
# runner's.
- name: ULP report
run: |
BASE="HWY_AVX10_2|HWY_AVX3_SPR|HWY_AVX3_ZEN4|HWY_AVX3_DL|HWY_AVX3"
cmake -B build -G Ninja -DCORVUS_WERROR=ON \
-DCORVUS_DISABLED_TARGETS="$BASE"
cmake --build build
export CORVUS_EXPECT_TARGET=AVX2
# Dependency order, dd cores first: a foundation regression should
# fail here under its own name, not a consumer's.
./build/tests/test_exp_dd tests/data/exp_dd_reference.txt
./build/tests/test_log_dd tests/data/log_dd_reference.txt
./build/tests/test_dd_special tests/data/dd_special_reference.txt
./build/tests/test_erf_ulp tests/data/erf_reference.txt
./build/tests/test_erfc_ulp tests/data/erfc_reference.txt
./build/tests/test_lgamma_ulp tests/data/lgamma_reference.txt
./build/tests/test_erfinv_ulp \
tests/data/erfinv_reference.txt tests/data/erfcinv_reference.txt
./build/tests/test_gamma_ulp \
tests/data/gamma_p_reference.txt tests/data/gamma_q_reference.txt
./build/tests/test_beta_ulp \
tests/data/beta_p_reference.txt tests/data/beta_q_reference.txt
./build/tests/test_digamma_ulp tests/data/digamma_reference.txt
./build/tests/test_trigamma_ulp tests/data/trigamma_reference.txt
./build/tests/test_gammainv_ulp \
tests/data/gammainv_p_reference.txt \
tests/data/gammainv_q_reference.txt
./build/tests/test_betainv_ulp \
tests/data/betainv_p_reference.txt \
tests/data/betainv_q_reference.txt
./build/tests/test_bessel_ulp \
tests/data/i0_reference.txt tests/data/i1_reference.txt \
tests/data/i0e_reference.txt tests/data/i1e_reference.txt
./build/tests/test_lbeta_ulp tests/data/lbeta_reference.txt
./build/tests/test_trig_ulp \
tests/data/cos_reference.txt tests/data/sin_reference.txt
./build/tests/test_exp_ulp tests/data/exp_reference.txt
./build/tests/test_log_ulp \
tests/data/log_reference.txt tests/data/log1p_reference.txt
# The examples self-verify and return non-zero on failure (see
# examples/CMakeLists.txt — deliberately outside ctest so a green ctest
# stays a pure accuracy statement). Run them from the AVX2-capped build
# the ULP report leaves behind; sub-second each. (#25)
- name: Run examples (smoke)
run: |
for ex in normal_distribution chi_squared_test gamma_mle_fit \
students_t von_mises_density log_space_counting; do
echo "::group::$ex"
./build/examples/$ex
echo "::endgroup::"
done
- name: Sanitizers (ASan+UBSan, Debug)
run: |
cmake -B build-san -G Ninja -DCMAKE_BUILD_TYPE=Debug \
-DCORVUS_SANITIZE="address;undefined"
cmake --build build-san
UBSAN_OPTIONS=halt_on_error=1 \
ctest --test-dir build-san --output-on-failure
# -----------------------------------------------------------------
# Install-contract smoke test — installed-path build, separate from
# the tier-sweep dirs above. Builds the PINNED Highway (1.4.0, the
# accuracy-audit version) into a prefix so find_package(hwy 1.4)
# resolves it as a system install (CORVUS_HWY_PROVIDER=system),
# which gates the install rules. Distro libhwy-dev is deliberately
# NOT used: Ubuntu ships Highway 1.0.x, far below the audited 1.4
# pin the version floor protects (see FindOrFetchHighway.cmake --
# the floor is the accuracy-audit pin, not any single op).
# -----------------------------------------------------------------
# Cache the installed Highway prefix: building 1.4.0 from source costs
# ~2-4 min per run. Key = pin + runner OS/arch; exact-match only (no
# restore-keys) so a pin bump always rebuilds. This is the "add caching
# only if minutes grow" trigger from the CI policy — the source build
# of Highway is what grew the minutes.
- name: Cache pinned Highway prefix
id: cache-hwy
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: _hwy
key: hwy-1.4.0-${{ runner.os }}-${{ runner.arch }}
- name: Build pinned Highway into prefix
if: steps.cache-hwy.outputs.cache-hit != 'true'
run: |
git clone --depth 1 --branch 1.4.0 https://github.com/google/highway.git _hwy-src
cmake -S _hwy-src -B _hwy-src/build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DHWY_ENABLE_TESTS=OFF -DHWY_ENABLE_EXAMPLES=OFF \
-DHWY_ENABLE_CONTRIB=ON -DBUILD_TESTING=OFF \
-DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/_hwy"
cmake --build _hwy-src/build
cmake --install _hwy-src/build
- name: Configure, build, install corvus (system Highway)
run: |
cmake -B build-install -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/_hwy" \
| tee configure.log
grep -q "using system Highway" configure.log
cmake --build build-install
cmake --install build-install --prefix "$GITHUB_WORKSPACE/_install"
- name: Configure and build consumer_example against installed prefix
run: |
cmake -S consumer_example -B consumer_example/build -G Ninja \
-DCMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/_install;$GITHUB_WORKSPACE/_hwy"
cmake --build consumer_example/build
- name: Run consumer_example
run: ./consumer_example/build/consumer_demo
- name: pkg-config consumer (compile, link, run with the plain flags)
run: |
export PKG_CONFIG_PATH="$GITHUB_WORKSPACE/_install/lib/pkgconfig:$GITHUB_WORKSPACE/_hwy/lib/pkgconfig"
pkg-config --exists --print-errors corvus
pkg-config --cflags --libs corvus
# Deliberately no --static: corvus.pc must carry Highway in
# Requires (not Requires.private) because libcorvus.a is static.
# Split into an array on purpose: the flags are separate arguments.
read -ra pc_flags <<< "$(pkg-config --cflags --libs corvus)"
g++ -o pc_consumer consumer_example/main.cpp "${pc_flags[@]}"
./pc_consumer
# -------------------------------------------------------------------------
# Windows / MSVC — toolchain coverage. This job deliberately produces NO new
# tier information: Highway blocklists every AVX3* target under real MSVC
# (HWY_BROKEN_MSVC), so dispatch tops out at AVX2 no matter how capable the
# runner's silicon is. That is what makes CORVUS_EXPECT_TARGET=AVX2 stable
# here without any capping — the blocklist pins the ceiling for us, and
# since #36 corvus states the same cap itself (cmake/ToolchainGuard.cmake).
#
# What it *does* catch, and nothing else in this workflow can:
# - MSVC-only diagnostics (/W4 /WX via CORVUS_WERROR). Real precedent: the
# C4566 Unicode-docstring warnings found in the sibling Python bindings,
# and the C4996 getenv deprecation this job caught on its first run.
# - The multi-config generator path. A set_property(CACHE CMAKE_BUILD_TYPE)
# bug made the VS generator fail at configure while Ninja was fine, so
# both other jobs were blind to it. No -G is passed on purpose: CMake's
# default on Windows is the newest installed Visual Studio, which is both
# multi-config and version-agnostic as runner images move. It also needs
# no vcvars shell and no third-party setup action.
#
# Do NOT add -DCORVUS_MSVC_UNBLOCK_AVX512=ON here. It would make this job
# dispatch AVX-512 and report a green "Windows passing" that reads as
# AVX-512 validation, on a code path upstream Highway declares untested and
# on runner silicon whose ISA level is not guaranteed. AVX-512 validation is
# a manual stop on the Ryzen box; see docs/ACCURACY.md.
# -------------------------------------------------------------------------
windows-msvc:
name: Windows x86-64 (MSVC toolchain)
runs-on: windows-latest
timeout-minutes: 25
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Multi-config: no CMAKE_BUILD_TYPE, hence --config/-C on build and test.
- name: Configure (default VS generator, multi-config)
run: cmake -B build -DCORVUS_WERROR=ON
- name: Build
run: cmake --build build --config Release
- name: Test
run: |
CORVUS_EXPECT_TARGET=AVX2 \
ctest --test-dir build -C Release --output-on-failure
# Not new audit data (AVX2 duplicates the Linux row), but it keeps
# ACCURACY.md's "MSVC reproduces these values" claim auditable in the log
# rather than resting on one local measurement.
- name: ULP report
run: |
export CORVUS_EXPECT_TARGET=AVX2
# Dependency order, dd cores first: a foundation regression should
# fail here under its own name, not a consumer's.
./build/tests/Release/test_exp_dd.exe tests/data/exp_dd_reference.txt
./build/tests/Release/test_log_dd.exe tests/data/log_dd_reference.txt
./build/tests/Release/test_dd_special.exe tests/data/dd_special_reference.txt
./build/tests/Release/test_erf_ulp.exe tests/data/erf_reference.txt
./build/tests/Release/test_erfc_ulp.exe tests/data/erfc_reference.txt
./build/tests/Release/test_lgamma_ulp.exe tests/data/lgamma_reference.txt
./build/tests/Release/test_erfinv_ulp.exe \
tests/data/erfinv_reference.txt tests/data/erfcinv_reference.txt
./build/tests/Release/test_gamma_ulp.exe \
tests/data/gamma_p_reference.txt tests/data/gamma_q_reference.txt
./build/tests/Release/test_beta_ulp.exe \
tests/data/beta_p_reference.txt tests/data/beta_q_reference.txt
./build/tests/Release/test_digamma_ulp.exe tests/data/digamma_reference.txt
./build/tests/Release/test_trigamma_ulp.exe tests/data/trigamma_reference.txt
./build/tests/Release/test_gammainv_ulp.exe \
tests/data/gammainv_p_reference.txt \
tests/data/gammainv_q_reference.txt
./build/tests/Release/test_betainv_ulp.exe \
tests/data/betainv_p_reference.txt \
tests/data/betainv_q_reference.txt
./build/tests/Release/test_bessel_ulp.exe \
tests/data/i0_reference.txt tests/data/i1_reference.txt \
tests/data/i0e_reference.txt tests/data/i1e_reference.txt
./build/tests/Release/test_lbeta_ulp.exe tests/data/lbeta_reference.txt
./build/tests/Release/test_trig_ulp.exe \
tests/data/cos_reference.txt tests/data/sin_reference.txt
./build/tests/Release/test_exp_ulp.exe tests/data/exp_reference.txt
./build/tests/Release/test_log_ulp.exe \
tests/data/log_reference.txt tests/data/log1p_reference.txt
# #36 toolchain guard, against a real mingw-w64 GCC (the runner image
# ships one on PATH). Configure-only — no build, and the Highway checkout
# from the MSVC configure above is reused — so the guard's probe and both
# of its mingw outcomes are exercised for seconds, not a second job. The
# verdict logic itself runs on every leg as the toolchain_guard ctest.
- name: Toolchain guard (mingw GCC, configure-only)
run: |
g++ --version | head -1
HWY_SRC="$PWD/build/_deps/highway-src"
common=(-G Ninja -DCMAKE_CXX_COMPILER=g++ -DCORVUS_BUILD_TESTS=OFF
"-DFETCHCONTENT_SOURCE_DIR_HIGHWAY=$HWY_SRC")
echo "::group::uncapped mingw GCC must be refused, naming the GCC PR"
if cmake -B build-guard-reject "${common[@]}" > guard-reject.log 2>&1; then
cat guard-reject.log
echo "::error::uncapped mingw GCC configured; the #36 guard did not fire"
exit 1
fi
cat guard-reject.log
grep -q "GCC PR 126741" guard-reject.log
grep -q "CORVUS_ALLOW_UNSUPPORTED_TOOLCHAIN" guard-reject.log
echo "::endgroup::"
echo "::group::mingw GCC capped to the 128-bit tiers must configure"
cmake -B build-guard-capped "${common[@]}" \
"-DCORVUS_DISABLED_TARGETS=(HWY_AVX2|(HWY_AVX2-1))"
echo "::endgroup::"
macos-arm64:
name: macOS arm64 (NEON)
runs-on: macos-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install Highway
run: brew install highway
# Native dispatch, but the tier is still asserted: this job is the sole
# source of the NEON row in docs/ACCURACY.md, so if a runner-image change
# ever moves dispatch (e.g. to NEON_BF16 on newer cores) that must fail
# loudly and be revalidated, not silently relabel the audit record.
- name: Build and test
run: |
cmake -B build -G Ninja -DCORVUS_WERROR=ON \
-DCMAKE_PREFIX_PATH="$(brew --prefix)"
cmake --build build
CORVUS_EXPECT_TARGET=NEON \
ctest --test-dir build --output-on-failure
# ctest hides output on success; run the ULP gates directly so the
# measured per-tier numbers land in the log for the audit record.
- name: ULP report
run: |
export CORVUS_EXPECT_TARGET=NEON
# This job is the only source of ACCURACY.md's NEON numbers.
# Dependency order, dd cores first: a foundation regression should
# fail here under its own name, not a consumer's.
./build/tests/test_exp_dd tests/data/exp_dd_reference.txt
./build/tests/test_log_dd tests/data/log_dd_reference.txt
./build/tests/test_dd_special tests/data/dd_special_reference.txt
./build/tests/test_erf_ulp tests/data/erf_reference.txt
./build/tests/test_erfc_ulp tests/data/erfc_reference.txt
./build/tests/test_lgamma_ulp tests/data/lgamma_reference.txt
./build/tests/test_erfinv_ulp \
tests/data/erfinv_reference.txt tests/data/erfcinv_reference.txt
./build/tests/test_gamma_ulp \
tests/data/gamma_p_reference.txt tests/data/gamma_q_reference.txt
./build/tests/test_beta_ulp \
tests/data/beta_p_reference.txt tests/data/beta_q_reference.txt
./build/tests/test_digamma_ulp tests/data/digamma_reference.txt
./build/tests/test_trigamma_ulp tests/data/trigamma_reference.txt
./build/tests/test_gammainv_ulp \
tests/data/gammainv_p_reference.txt \
tests/data/gammainv_q_reference.txt
./build/tests/test_betainv_ulp \
tests/data/betainv_p_reference.txt \
tests/data/betainv_q_reference.txt
./build/tests/test_bessel_ulp \
tests/data/i0_reference.txt tests/data/i1_reference.txt \
tests/data/i0e_reference.txt tests/data/i1e_reference.txt
./build/tests/test_lbeta_ulp tests/data/lbeta_reference.txt
./build/tests/test_trig_ulp \
tests/data/cos_reference.txt tests/data/sin_reference.txt
./build/tests/test_exp_ulp tests/data/exp_reference.txt
./build/tests/test_log_ulp \
tests/data/log_reference.txt tests/data/log1p_reference.txt