Conversation
HMMER/Easel's fast profile-HMM filters only exist as hand-written SSE/NEON/VMX kernels, so CMakeLists.txt hard-fails on riscv64; route the SSE path through SIMDe instead, with a build-time header shim so the vendored sources (and pyhmmer's own line-number-based patches against them) stay untouched. Also fixes esl_cpu.c's x86-only CPUID assembly and packages the vendored HMMER/Easel licences.
luhenry
added a commit
that referenced
this pull request
Sep 8, 2026
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.
pyhmmer0.12.3Compiles vendored HMMER3/Easel and Cython bindings for profile-HMM search. Upstream publishes no riscv64 wheel.
Mirrors upstream's
package.yml(wheel-linux-x86_64/wheel-linux-aarch64jobs).Status: parked. Builds and links cleanly, but CI found a real riscv64-only correctness bug:
p7_MSVFilter()returns wrong scores (hit counts of0where real hits are expected, or under-counts like479 != 482). Root cause not isolated despite a thorough investigation (below); parking rather than merging a wheel that produces silently wrong search results.Differs from upstream
esl_cpu.c's x86-only CPUID assembly is skipped on that path.License: Wheel bundles vendor/hmmer (BSD-3-Clause) and vendor/easel (BSD-2-Clause); pyhmmer's own
license-filesomits them, so a patch adds both.Investigation (real riscv64 hardware and real riscv64/GCC 14.3.1 via QEMU, not just the QEMU rehearsal used to validate the build):
expf/logfapproximations inesl_sse.c(relative error ~6e-9 avg, ~1.2e-7 max - at float precision, matching arm64).p7_MSVFilterfails its own unit test withscores differ (-21.25, -10.86)- a ~10-nat divergence, not a rounding artifact.p7_SSVFilter's internal fast-path shortcut is active or force-disabled - rules outssvfilter.c's control flow specifically.-O1,-O2,-O3- rules out an optimization-level-triggered miscompilation._mm_max_epu8/_mm_adds_epu8/_mm_subs_epu8), the byte-lane shift (_mm_slli_si128), the horizontal-max reduction chain, and theunion { __m128i; uint8_t[16]; }type-pun pattern used to buildom->rbv.p7_GViterbi, pure portable C, no SIMD/SIMDe) passes its own internal self-consistency check (score vs. independently-reconstructed optimal-trace score) on real riscv64, making it unlikely to be the source of the divergence.p7_MSVFilterloop composes these (individually-correct) primitives across many iterations diverges specifically under riscv64/GCC - not isolated to an exact line. Likely needs a real riscv64 GCC debugger session or upstream HMMER/SIMDe maintainer input. Written up as gotcha 332 in the porting skill for the next attempt.Patches
0001-CMake-...patch- Inappropriate. Adds the SIMDe fallback since riscv64 has no native SIMD backend; riscv64-only.0002-easel-...patch- To upstream. Fixesesl_cpu.c's CPUID assembly breaking under the SIMDe path; riscv64-only.0003-package-the-licences-...patch- To upstream. Packages the vendored licences; same gap on every platform.