Make the architecture options mean what they say - #9
Merged
Merged
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 40387c383e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Nothing in CI configures with FINE_TUNE=ON, so the option's per-platform behaviour is unverified on all six targets. It is the configuration most likely to break silently: the flag that targets the host CPU is spelled differently per architecture and compiler, so a wrong spelling either fails the build or is dropped with no effect on the generated code. Add a FINE_TUNE=ON build to each matrix job, alongside the existing HPTT_BUILD_SHARED=OFF one, and check it two ways. Building catches the hard-error case. Grepping build-fine-tune/compile_commands.json for a host-tuning flag catches the silent no-op, which a green build would otherwise hide; the check is skipped on Windows because MSVC has no such flag on any architecture. The downstream consumer from tests/downstream_find_package then runs against that build tree, so the fine-tuned library is also checked for correct results rather than only for compiling. Co-Authored-By: Claude <noreply@anthropic.com>
FINE_TUNE was implemented as one flag per compiler family: -march=native
for GNU and Clang, -xhost for Intel. That structure leaves the option
either wrong or absent on several targets:
* On AArch64 the flag that selects the host ISA together with its
scheduling model is -mcpu=native. -march= there names an architecture
revision only, so it asks for something narrower than intended.
* On POWER, -march= does not exist ("unsupported option '-march=' for
target 'powerpc64le-...'"). FINE_TUNE was excluded from the ENABLE_IBM
path anyway, silently doing nothing.
* GNU on Apple took an APPLE branch that ignored FINE_TUNE entirely and
applied -mtune=native unconditionally instead, so FINE_TUNE=ON never
reached -march=native there.
* MSVC and IntelLLVM (icpx, whose compiler id is not "Intel") matched no
branch at all, so FINE_TUNE=ON was a silent no-op on those toolchains.
* On Apple Silicon FINE_TUNE=ON put -march=native on the same compile
line as the -mcpu=native the APPLE block adds below, leaving two
host-tuning flags with different meanings to fight over the target.
Choose the flag by what the target accepts instead. The architecture
fixes the order the candidates are offered in -- -march=native first on
x86, -mcpu=native first elsewhere, -mtune=native last everywhere -- and
check_cxx_compiler_flag decides which one the toolchain in hand really
takes. Both halves are needed: probing alone would pick -mcpu=native on
x86 GCC, which only warns that the flag is deprecated while setting
nothing but scheduling, and Clang rejects it outright ("unsupported
option '-mcpu=' for target 'x86_64-...'"). A compiler that accepts no
candidate now says so through message(WARNING) rather than dropping the
request without a word, and CMAKE_CROSSCOMPILING warns that `native`
reads the build machine, not the target.
-xhost becomes a FINE_TUNE candidate rather than an unconditional flag.
It is Intel's spelling of exactly what FINE_TUNE asks for -- code for the
highest ISA the compiling host supports -- so applying it with
FINE_TUNE=OFF made every Intel build non-portable against the option's
documented default.
On x86 GCC the emitted flags become -march=native alone, where they were
-march=native -mtune=native. That pair is redundant: `g++ -march=native
-Q --help=target` reports -mtune=cascadelake on this host, identical to
passing -mtune=native explicitly, `-Q --help=target` shows no difference
in any target option between the two, and the two flag sets compile
src/plan.cpp to byte-identical assembly.
Co-Authored-By: Claude <noreply@anthropic.com>
FINE_TUNE defaults to OFF and warns that turning it on produces non-portable binaries, but two paths tuned for the build machine's CPU without consulting it. The Apple Silicon branch appended -mcpu=native. That sets the target ISA, not just scheduling, and Apple Silicon generations do not share one ISA, so an HPTT built on an M4 could fault on an M1 -- reached by anyone building on a Mac, including wheel and package builds, with nothing in the configuration asking for it. It also collided with FINE_TUNE=ON, which added a second, differently spelled host-tuning flag to the same compile line. The ENABLE_IBM branch appended -mtune=native. -maltivec and -mabi=altivec stay: AltiVec is a baseline every supported POWER chip has, so those two remain portable across the architecture, while the -mtune= value is specific to the chip that ran the build. FINE_TUNE=ON restores host tuning on both platforms, now through the single flag selected for the target. Co-Authored-By: Claude <noreply@anthropic.com>
HPTT is distributed as a binary, so the configuration users actually receive must not depend on the machine that produced it. A `native`-tuned artifact targets the ISA of the build host and can fault on a different CPU of the same architecture, and nothing in CI states that the default configuration stays clear of that. Grep build/compile_commands.json for -march/-mcpu/-mtune=native and -xhost right after the default build, and fail with the offending flag named. FINE_TUNE=ON is the documented way to ask for host tuning; this asserts it is the only way to arrive there. The check runs on every platform, MSVC included, because "no host-tuning flag" is the expected answer everywhere -- unlike the FINE_TUNE=ON check further down, which has to skip Windows for want of any such flag to find. Verified to fail before the flags were gated: on the previous revision the Apple Silicon branch appended -mcpu=native and the Intel branch appended -xhost with no reference to FINE_TUNE, so macos-arm64 and any ICC build would have tripped this step. Co-Authored-By: Claude <noreply@anthropic.com>
ENABLE_ARM defaulted OFF everywhere, so a default build on aarch64 took the generic scalar path with REGISTER_BITS=256 -- a 256-bit blocking factor on a machine whose vector registers are 128 bits wide. The Neon micro-kernels in src/transpose.cpp were reachable only by passing -DENABLE_ARM=ON by hand. Nothing about that default was protecting portability. Advanced SIMD is mandatory in every ARMv8-A implementation, which is why there is no `-mfpu` option on those targets to switch it on with: a CPU that can run the library at all already has the instructions. So ON is correct on aarch64 even for a redistributed binary, and the option keeps defaulting OFF on 32-bit ARM, where Neon really is an optional extension. Apple Silicon already had this: the APPLE branch appends HPTT_ARCH_ARM regardless of ENABLE_ARM, so macOS arm64 has been using the Neon kernels while Linux aarch64 and Windows ARM64 used the scalar ones from the same default configuration. CMake de-duplicates COMPILE_DEFINITIONS, so the two paths appending it together put it on the compile line once. Hoist the architecture tests to two predicates above the options, since the ENABLE_ARM default, the baseline -march and the host-tuning probe order all key off the same two questions; the -mfpu=neon guard now reads through HPTT_TARGET_IS_ARM64 rather than repeating the regex. The ARM CI jobs drop their explicit -DENABLE_ARM=ON, so the downstream consumer exercises the Neon kernels through the configuration a user actually gets. A new step asserts HPTT_ARCH_ARM reaches the compile line on ARM64 runners: scalar HPTT is correct, only slower, so a regression in this default would otherwise leave every check in the job green. Co-Authored-By: Claude <noreply@anthropic.com>
benchmark/reference.cpp does not compile. transpose_ref is explicitly
instantiated for float and double, and its conjugating branch reads
B_[i] = alpha * std::conj(A_[i * strideAinner]);
Since C++11 the std::conj overload taking an arithmetic argument returns
std::complex<T>, and std::complex<double> has no conversion back to
double, so both real instantiations fail:
error: cannot convert 'std::complex<double>' to 'double' in assignment
Both element types HPTT benchmarks by default are real -- defines.h
typedefs floatType to float -- so the benchmark could not be built at all.
Conjugation is the identity on reals, so dispatch on the element type
through a conj_ref helper that stays inside floatType, overloaded for
std::complex<T>. The complex instantiations keep calling std::conj and
the real ones now compile.
Co-Authored-By: Claude <noreply@anthropic.com>
The three ENABLE_* options each imply an assumption about the target, but none of them said which, and none checked. ENABLE_ARM=ON on an x86 target put `-mfpu=neon` and Neon intrinsics on an x86 compile line and failed deep in the build; ENABLE_AVX=ON on arm64 emitted `-mavx` the same way. State the floor for each option and enforce it at configure time: * ENABLE_AVX assumes x86-64-v3 -- AVX, AVX2 and FMA -- and is refused on a non-x86 target. The floor is now `-march=x86-64-v3` (GCC 11+/Clang 12+; `-mavx -mavx2 -mfma` where the level name is unknown) or `/arch:AVX2` under MSVC, replacing the bare `-mavx` that only guaranteed AVX. Benchmarked on this tree: v3 plus the AVX kernels reaches 25-31 GiB/s against 12-14 for the scalar default on the 2D and 3D-perm210 cases, while `-mavx` alone leaves the non-kernel paths unvectorized and AVX-512 adds nothing to a 256-bit transpose kernel. * ENABLE_ARM assumes an ARMv8-A arm64 target and is refused anywhere else, 32-bit ARM included. Advanced SIMD is mandatory in ARMv8-A, so no flag selects it and `-mfpu=neon` disappears: it is a 32-bit-only spelling that aarch64 rejects, and 32-bit ARM is no longer in scope for the option. * ENABLE_IBM assumes a POWER target, matched by a new HPTT_TARGET_IS_POWER predicate, and is refused elsewhere. FINE_TUNE moves below these blocks. The compiler honours the last -march on the command line, so `-march=native` has to be appended after any baseline -- otherwise ENABLE_AVX's v3 floor would silently downgrade FINE_TUNE=ON to v3. The x86-64 baseline is skipped when ENABLE_AVX sets a higher one, leaving one -march and a generic -mtune rather than two. macOS stops choosing kernels for itself. The APPLE branch appended HPTT_ARCH_AVX or HPTT_ARCH_ARM regardless of the options, which would now override an explicit -DENABLE_AVX=OFF. Its arch-independent optimization flags stay; kernel selection goes through the options, whose defaults already match Apple hardware: ENABLE_ARM=ON on arm64, and ENABLE_AVX=ON on an Intel Mac, where the v3 floor is safe because the oldest Intel Mac any supported macOS runs on is a 2013 Haswell. CI gains a negative test -- the option that cannot apply to the runner must fail configure with the diagnostic -- and an ENABLE_AVX=ON build plus consumer run on the x86 jobs, covering MSVC's /arch:AVX2 spelling that no job exercised before. Co-Authored-By: Claude <noreply@anthropic.com>
The architecture checks sat inside the if/elseif chain that picks the
micro-kernels, so only the branch that matched ever ran its check. With
ENABLE_AVX defaulting ON on an Intel Mac, `-DENABLE_ARM=ON` there took the
ENABLE_AVX branch, passed its x86 check, and left ENABLE_ARM accepted and
silently ignored -- the exact case the option is supposed to reject. The
macos-x64 job caught it.
Hoist all three checks above the chain so each option is validated on its
own regardless of which one ends up selecting kernels. Rejecting each
option on the wrong architecture also makes two of them on at once
impossible to configure, since ENABLE_AVX requires x86 and ENABLE_ARM
requires arm64.
Also fix the path the ENABLE_AVX CI step used. It assigned
`AVXDIR=${{ github.workspace }}/build-avx` unquoted, and quote removal
strips the backslashes of `D:\a\hptt\hptt` on Windows, so the step looked
for `D:ahptthptt/build-avx/compile_commands.json` and failed there. The
directory now comes from the job's env block alongside FINE_TUNE_DIR,
which is how the other steps already avoid this.
Co-Authored-By: Claude <noreply@anthropic.com>
CMAKE_SYSTEM_PROCESSOR does not name the target on an MSVC cross build. Modules/CMakeDetermineSystem.cmake derives it from the compiler only for WindowsCE; every other configuration copies CMAKE_HOST_SYSTEM_PROCESSOR into it. So `vcvarsall x64_arm64` with the Ninja generator and no toolchain file reports AMD64 while cl.exe targets ARM64, and CMAKE_CROSSCOMPILING does not flag it either, because CMake clears that unless CMAKE_SYSTEM_NAME was supplied. The architecture predicates read that variable, so such a build was classified as x86: the default omitted the Neon kernels, and -DENABLE_ARM=ON now hit the wrong-architecture FATAL_ERROR even though it configured and compiled before -- MSVC never received `-mfpu=neon`, being neither GNU nor Clang, so HPTT_ARCH_ARM alone was enough. That is a regression introduced with those checks. Prefer MSVC_CXX_ARCHITECTURE_ID, which CMake fills from the compiler's own _M_* macros and therefore names the target. It is set only for MSVC and clang-cl, so CMAKE_SYSTEM_PROCESSOR remains the source everywhere else. The x86 pattern gains MSVC's `x64` and `X86` spellings, without which a native Windows x64 build would stop matching once the id becomes the source. MSVC's `IA64` is Itanium and stays excluded, as does 32-bit `ARM`; `ARM64EC` matches the 64-bit ARM pattern already. All fourteen spellings the two sources can produce were checked against the patterns. The cross build itself is unverified here: no MSVC toolchain is available in this environment, and CI's windows-arm64 runner is native ARM64 rather than an x64 host cross-compiling. What CI does cover is that the new source is correct natively on both Windows jobs -- x64 must keep satisfying the x86 pattern for the ENABLE_AVX step, and ARM64 must keep satisfying the arm64 pattern for the Neon-default check. Co-Authored-By: Claude <noreply@anthropic.com>
The FINE_TUNE consumer died with SIGILL on linux-x64 while ccache reported 32 hits out of 32 calls. ccache keys a compilation on the literal flag string, and `-march=native` does not record which CPU it resolved to, so an object compiled on one machine is served as a hit for the same flag on another. The hosted runner fleet is not homogeneous, so the cache restored from an earlier run handed the job a libhptt built for a different CPU and the consumer executed instructions this one does not implement. That is the failure this branch exists to prevent, arriving through the build cache instead of through a release artifact, so the fix is to compile the fine-tuned objects fresh rather than to teach the cache a better lie. Drop the compiler launchers from that one configure. Everything else keeps ccache. The default, ENABLE_AVX and static-only builds name their architecture explicitly -- `-march=x86-64`, `-march=x86-64-v3`, `/arch:AVX2` -- so an object is valid on any machine that produced a hit. The consumer keeps it too: HPTT's architecture flags are PRIVATE, so consumer.cpp is compiled without them and only links the freshly built library. Co-Authored-By: Claude <noreply@anthropic.com>
ENABLE_AVX defaulted ON when targeting an Intel Mac and ENABLE_ARM
defaulted ON on any 64-bit ARM target, so what a plain `cmake ..` produced
depended on the platform it ran on: Neon kernels on arm64, AVX kernels over
an x86-64-v3 floor on an Intel Mac, portable scalar everywhere else. That
disagreed with README.md, which lists all three ISA options as "Optionally
one of ...", and with the Makefile targets they come from, where `make avx`,
`make arm` and `make ibm` are each an explicit request.
Default all four OFF on every platform. A default build is the portable one
everywhere, each departure from portability is named by whoever runs the
build, and the target architecture's only remaining say over these options
is to reject one it cannot honour.
The three validations move up to sit directly beneath the option() calls,
making that veto the single place architecture and option meet. The
`NOT ENABLE_IBM` guard on the GNU baseline -march goes with them: it is
redundant beside the HPTT_TARGET_IS_X86 test in the same condition, an x86
target being the one place ENABLE_IBM cannot be on.
The validation diagnostics quote hptt_target_arch rather than
CMAKE_SYSTEM_PROCESSOR. Those two disagree under an MSVC cross build, where
the message would otherwise name the host architecture while rejecting an
option for targeting the wrong one, reading as a contradiction of the error
it reports.
On arm64 a default build now compiles the scalar path with REGISTER_BITS=256,
that macro defaulting to 256 in include/hptt_types.h with only HPTT_ARCH_ARM
lowering it to 128. This is the configuration x86 default builds have always
used; ENABLE_ARM=ON is what selects the Neon kernels and 128 again.
CI keeps pace on both sides:
- "Check the default build is portable" additionally requires that no
HPTT_ARCH_* macro reach the compile line, on all six platforms. It has
to exist because the scalar fallback is correct: an ISA option turning
itself on changes nothing any other check in the job looks at.
- Every job builds the one ISA option its architecture accepts and runs
the downstream consumer against it -- ENABLE_ARM on the ARM64 runners,
ENABLE_AVX on the x86 ones. Nothing else would compile the Neon kernels
with the default no longer selecting them, and the two options are
symmetric enough to share one step.
- The matrix drops arch_flags, empty on all six entries and with no
remaining caller.
Verified on x86_64 / GCC 13.3: the default build carries -march=x86-64
-mtune=generic and no HPTT_ARCH_* macro, -DENABLE_AVX=ON carries
-march=x86-64-v3 and HPTT_ARCH_AVX, -DFINE_TUNE=ON carries -march=native.
-DENABLE_ARM=ON, -DENABLE_IBM=ON, and the pairs -DENABLE_AVX=ON
-DENABLE_ARM=ON and -DENABLE_ARM=ON -DENABLE_IBM=ON are each refused at
configure time with a message the CI grep matches. The scalar default and
the ENABLE_AVX build both pass the downstream consumer's correctness checks.
Co-Authored-By: Claude <noreply@anthropic.com>
The CMake section lists the three ENABLE_* variants but not FINE_TUNE, so reading CMakeLists.txt is the only way to find it. It is also the option whose consequence a reader most needs warning about: the binary it produces runs only where the build machine's CPU features are present. That matters on the way in as much as the way out, the Makefile's default g++ flags carrying -march=native, so someone moving from `make` to CMake would otherwise notice neither the loss of host tuning nor how to ask for it back. Co-Authored-By: Claude <noreply@anthropic.com>
IvanaGyro
force-pushed
the
claude/arm64-fine-tune-flag-rzdq81
branch
from
July 30, 2026 14:03
c5de6c1 to
4c09d59
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follows #6, which added the CI matrix and fixed
-march=x86-64and-mfpu=neonon non-x86 targets. This does the same for the remaining options: each one states an ISA floor, is opt-in, is rejected on a target that cannot honour it, and is checked by CI.Status
Run 30549861824 on
4c09d59: linux-x64, linux-arm64, macos-x64, macos-arm64, windows-x64, windows-arm64 — 6/6 pass.Problem
Four separate defects, none of which any CI job covered:
1. Default builds were keyed to the machine that compiled them. HPTT is redistributed, but the Apple Silicon branch appended
-mcpu=native, the Apple GNU branch-mtune=native,ENABLE_IBM-mtune=native, and the Intel branch-xhost— all withFINE_TUNE=OFF, whose own help text promises portable binaries.-march=native/-mcpu=nativeselect the ISA of the build host, not an architecture: on this Cascade Lake builder-march=nativeemitskmovb,kortestbandvblendmps, so the artifact needs AVX-512 and faults on any AMD Zen 1–3 or any Intel 12th-gen-or-later consumer part, all of which arex86_64.2.
FINE_TUNE=ONwas a no-op on four toolchains. GNU on macOS took anAPPLEbranch that ignored it;ENABLE_IBM=ONexcluded it viaelseif(NOT ENABLE_IBM); MSVC and IntelLLVM (icpx, whose compiler id is notIntel) matched no branch at all. On Apple Silicon it was worse than absent —-march=nativelanded on the same command line as the-mcpu=nativeabove it, two host-tuning flags with different meanings.3. The same default configuration behaved differently on the three arm64 platforms.
ENABLE_ARMdefaulted OFF, but theAPPLEbranch definedHPTT_ARCH_ARMregardless of the options, so macOS arm64 got the Neon kernels andREGISTER_BITS=128while Linux and Windows arm64 got the scalar path and 256 — from an identical command line. Kernel selection lived in two places at once, and theAPPLEone won even against an explicit-DENABLE_ARM=OFF.4. The ISA options accepted architectures they cannot serve.
-DENABLE_ARM=ONon x86 put-mfpu=neonand Neon intrinsics on an x86 command line and failed deep in the build with an unrelated-looking error.benchmark/reference.cppalso did not compile:std::conjon an arithmetic argument returns a complex type since C++11, so both real instantiations failed and the benchmark could not be built at all.Fix
All four options default OFF on every platform, so a default build is the portable one everywhere and each departure from portability is named by whoever runs the build. The target architecture's only say over them is to reject one it cannot honour:
FINE_TUNE=ON-march=native(x86) /-mcpu=native(ARM, POWER) /-xhost(ICC, ICX), chosen by compile probeENABLE_AVX=ON-march=x86-64-v3 -mtune=generic, or/arch:AVX2under MSVCFATAL_ERRORENABLE_ARM=ONFATAL_ERRORENABLE_IBM=ON-maltivec -mabi=altivecFATAL_ERRORThe three ISA options are mutually exclusive by construction rather than by a separate rule: each names one architecture, the architecture predicates are mutually exclusive, so at most one survives validation on any given target. The validations sit directly beneath the
option()calls and all three always run — they cannot live inside theif/elseifselection chain, because a check in one branch never runs once an earlier option has matched, and-DENABLE_AVX=ON -DENABLE_ARM=ONwould then take the AVX branch and dropENABLE_ARMin silence.The host-tuning flag is probed, not assumed, because no single spelling works: Clang rejects
-mcpu=on x86 outright, GCC only warns that it is deprecated (so a bare probe would pick a flag that sets scheduling and nothing else), and-march=does not exist on POWER. Architecture fixes the candidate order,check_cxx_compiler_flagpicks the first the toolchain accepts, and a toolchain accepting none says so throughmessage(WARNING)instead of dropping the request silently — which is MSVC on both architectures, the only remaining case with no host-tuning flag at all.-mfpu=neonis gone. It is a 32-bit-ARM-only spelling, and withENABLE_ARMassuming ARMv8-A, 32-bit ARM is refused by the option rather than silently opted in. Verified:__ARM_NEONis predefined onaarch64-linux-gnubut not onarmv7a-linux-gnueabihforarmv6-linux-gnueabihf.macOS stops choosing kernels for itself. The
APPLEbranch appendedHPTT_ARCH_AVX/HPTT_ARCH_ARMregardless of the options, which would override an explicit-DENABLE_AVX=OFF. Its arch-independent optimization flags stay; kernel selection goes through the options on macOS exactly as on every other platform, which is what makes the three arm64 platforms agree. (An Intel Mac can always takeENABLE_AVX=ON— the oldest Intel Mac any supported macOS release runs on is a 2013 Haswell — but it is opt-in there like everywhere else.)Under MSVC the architecture comes from
MSVC_CXX_ARCHITECTURE_ID, notCMAKE_SYSTEM_PROCESSOR. CMake derives the latter from the compiler only for WindowsCE (Modules/CMakeDetermineSystem.cmake); every other build copies the host processor into it, sovcvarsall x64_arm64with the Ninja generator reportsAMD64whilecl.exetargets ARM64 — andCMAKE_CROSSCOMPILINGis not set either, because CMake clears it unlessCMAKE_SYSTEM_NAMEwas given. Without this, the new validation would reject a cross build that previously worked.FINE_TUNEmoved below the ISA blocks. The compiler honours the last-marchon the command line, so-march=nativemust come after the v3 floorENABLE_AVXsets, orFINE_TUNE=ONwould be silently downgraded to v3.Benchmark
The v3 floor for
ENABLE_AVXis measured, not assumed. Five variants oflibhpttdiffering only in HPTT's own flags, benchmark TU compiled once and linked against each — valid becauseexecute_expertis explicitly instantiated intranspose.cpp, so kernels take the library's flags. HPTT's own harness (best-of-5, 100 MB cache trash between reps), 4 threads, GiB/s, all on one 4-vCPU Cascade Lake host in one session:Three conclusions. Raising
-marchalone buys nothing (v3≈base) despite unlocking 66,835 ymm instructions — auto-vectorization is not the lever.HPTT_ARCH_AVXat a v3 floor is the whole win, ~1.8–2.1x, but only on genuine transposes; permutations whose inner stride is already 1 are memory-bound and show no ISA sensitivity. AVX-512 adds nothing —nativeis level withv3+AVXand sometimes slower.Caveat: this host is a shared 4-vCPU cloud instance and the bandwidth-bound rows vary up to 2.6x between identical runs, so those were re-measured with repeats. Treat the ~2x as reproducible and the exact figures as indicative.
Testing
New CI coverage, on top of the existing per-platform build +
find_packageconsumer runs:compile_commands.jsonfor-m(arch|cpu|tune)=native,-xhost, and anyHPTT_ARCH_*, failing with the leak named. Runs on all six platforms; verified to fail onmain, which emitted-mcpu=nativeand-xhostunconditionally. The ISA half is needed because the scalar fallback is correct, so an option turning itself on changes nothing any other check in the job looks at.-DENABLE_ARM=ONon the ARM64 runners,-DENABLE_AVX=ONon the x86 ones, in one step now that the two are symmetric. The macro is grepped for because a scalar fallback would pass the consumer either way, and the consumer then runs against the ISA build, so it is checked for correct results rather than only for compiling. This is first coverage of the/arch:AVX2path under MSVC.FINE_TUNE=ONbuilds and lands a flag — building catches the hard-error case, grepping catches the silent no-op a green build would hide; skipped on Windows, which has no such flag. The consumer runs against that build tree too.if/elseifchain, andENABLE_AVXdefaulted ON on an Intel Mac at that point, so-DENABLE_ARM=ONpassed the AVX branch's x86 check and was silently ignored. Fixed in9c1dfb0by hoisting all three checks above the chain.The fine-tuned objects are compiled without ccache, and that is load-bearing rather than tidiness. ccache keys on the literal flag string and cannot know which CPU
-march=nativeresolved to, so a cache restored from a differentubuntu-latestmachine served objects built for another CPU: the consumer died withIllegal instruction(exit 132) while ccache reportedHits: 32/32. That is precisely the shipped-artifact failure this PR is about, reproduced by the build cache on real hardware.Note for review
Twelve commits spanning four separable concerns —
FINE_TUNE/host-tuning (296d130–db61f75), the arm64 target predicate (2e893eb), the ISA floors and their validation (606a0f3,9c1dfb0,84f0567), and the uniform opt-in defaults (192a014) — plus the benchmark fix (c75e91e), the ccache fix (dfc049b) and a README line (4c09d59). Happy to split into stacked PRs if you would prefer to review them apart.One thing to know when reading the log:
2e893ebintroduces theHPTT_TARGET_IS_ARM64predicate and takesENABLE_ARMON by default for arm64;192a014later settles on uniform opt-in and takes that default back out. The predicate is what the validation depends on and survives; the default does not. Net effect at the tip is the predicate plus a uniform OFF.Two pre-existing warts left untouched, both worth deciding separately: macOS forces
-O3 -ffast-math -funroll-loops -ftree-vectorizeregardless ofCMAKE_BUILD_TYPE, so a macOS Debug build silently gets-O3and-ffast-mathchanges FP semantics on one platform only; and the legacy Makefiles (root,benchmark/,testframework/) still hardcode-march=native/-xhostwith no opt-in, withmake armstill adding-mfpu=neonthat GCC rejects on aarch64.