From b47bce7c3ba55714238ceda3086397189f8e734a Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Sat, 1 Aug 2026 21:58:36 +0200 Subject: [PATCH] ci: give the MSVC viewer /arch:AVX, and write down why -march lives in CI The Linux jobs already pass -march=x86-64-v3; the MSVC viewer job passed nothing, so it built at the x64 baseline. MSVC has no spelling for the x86-64-v2 level, but /arch:AVX is the nearest and implies SSE4.1/4.2 - which is the part that matters, because below SSE4.1 Eigen has no vectorised round and falls back to one libm call per element. AVX is Sandy Bridge and up, a safe floor for a desktop viewer. The architecture flags stay OUT of CMakeLists on purpose, so a site can build x86-64-v4 on an AVX-512 cluster, or -march=native, or the plain baseline. That is easy to mistake for an oversight and "fix", so say it in CLAUDE.md - together with the consequence that catches anyone profiling: a default local Release build is not what CI or production runs, and the gap is not uniform. GPU-bound work is unaffected, but the CPU and Eigen bound phases - first-pass indexing and scaling/merging - measure about 26% slower without the flags. That is enough to make rounding look like a tenth of all cycles when a real build has it nearly free, and to send a reader at the wrong code. Co-Authored-By: Claude Opus 5 (1M context) --- .gitea/workflows/build_and_test.yml | 6 +++++- CLAUDE.md | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/build_and_test.yml b/.gitea/workflows/build_and_test.yml index 661e08d5..07d27f5e 100644 --- a/.gitea/workflows/build_and_test.yml +++ b/.gitea/workflows/build_and_test.yml @@ -2,6 +2,10 @@ name: Build Packages env: MARCH_CMAKE_FLAGS: '-DCMAKE_CXX_FLAGS="-march=x86-64-v3" -DCMAKE_C_FLAGS="-march=x86-64-v3"' + # MSVC has no spelling for the x86-64-v2 level; /arch:AVX is the nearest and implies SSE4.1/4.2, + # which is what matters here - without it Eigen has no vectorised round and falls back to a libm + # call per element. AVX is Sandy Bridge (2011) and up, a safe floor for a desktop viewer. + MSVC_ARCH_CMAKE_FLAGS: '-DCMAKE_CXX_FLAGS="/arch:AVX" -DCMAKE_C_FLAGS="/arch:AVX"' on: push: @@ -83,7 +87,7 @@ jobs: run: | for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set "VSPATH=%%i" call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat" - cmake -G Ninja -B build -DJFJOCH_USE_CUDA=${{ matrix.use_cuda }} -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="C:/deps;C:/Qt/6.11.1/msvc2022_64" + cmake -G Ninja -B build -DJFJOCH_USE_CUDA=${{ matrix.use_cuda }} -DCMAKE_BUILD_TYPE=Release ${{ env.MSVC_ARCH_CMAKE_FLAGS }} -DCMAKE_PREFIX_PATH="C:/deps;C:/Qt/6.11.1/msvc2022_64" - name: Build viewer shell: cmd run: | diff --git a/CLAUDE.md b/CLAUDE.md index 3ea9c517..c043d8ec 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -43,6 +43,27 @@ Key CMake options: - `SLS9` (default OFF) — build against slsDetectorPackage 9.2.0 instead of 8.0.2. - `JFJOCH_INSTALL_DRIVER_SOURCE` (default OFF) — install the PCIe driver source for DKMS/RPM. +### `-march` is deliberately NOT set in CMakeLists + +The build system sets no architecture flags, so a site can pick its own — `x86-64-v4` on an +AVX-512 cluster, `-march=native`, or the plain baseline. **CI passes them explicitly** +(`.gitea/workflows/build_and_test.yml`): every Linux configure gets +`-march=x86-64-v3`, and the MSVC viewer job gets `/arch:AVX` (MSVC has no x86-64-v2 spelling; +`/arch:AVX` is the nearest and implies SSE4.1/4.2). + +**This matters when profiling.** A plain `cmake -DCMAKE_BUILD_TYPE=Release ..` produces a +*baseline* binary that is not what CI or production runs, and the difference is not uniform: +GPU-bound work is unaffected, but the CPU/Eigen-bound phases — first-pass indexing and +scaling/merging — are **~26% slower** without the flags (measured). Eigen in particular has no +vectorised `round` below SSE4.1 and falls back to a libm call per element, which can make +rounding look like ~10% of all cycles when it is nearly free in a real build. Pass the CI flags +when measuring anything CPU-side, or the profile will point at the wrong code: + +``` +cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=x86-64-v3" \ + -DCMAKE_C_FLAGS="-march=x86-64-v3" .. +``` + The frontend is a separate custom target: `make frontend` (in `frontend/`: `npm ci`, `npm run build`, plus the third-party-licenses, Redoc and Sphinx-docs bundling steps). It is never built automatically — `make install` only copies whatever already sits in `frontend/dist/`.