Description
haploid_highd.evolve() hangs indefinitely on ARM64 (Apple Silicon) when crossover_rate or mutation_rate are set before calling set_allele_frequencies(). This appears to be an ARM64-specific issue, as x86_64 CI tests pass successfully.
Environment
- Architecture: ARM64 (Apple M4 Max)
- OS: macOS 15.0.0 (Darwin 25.0.0)
- Python: 3.11
- Build: Fresh build with MACOSX_DEPLOYMENT_TARGET=14.0, C++11, GSL 2.8, Boost (Homebrew)
Root Cause
The hang occurs when:
- Setting
crossover_rate OR mutation_rate (or both)
- Calling
set_allele_frequencies()
- Then calling
evolve()
Reproduction
Script that HANGS on ARM64
import FFPopSim as h
import numpy as np
L = 10
N = 500
pop = h.haploid_highd(L)
pop.carrying_capacity = N
pop.outcrossing_rate = 1
pop.crossover_rate = 0.02 / L # Setting this causes the hang
# OR
# pop.mutation_rate = 0.1 / N # Setting this also causes the hang
initial_af = 0.5 * np.ones(L)
pop.set_allele_frequencies(initial_af, N)
# Hangs indefinitely on ARM64:
pop.evolve(10)
Result on ARM64: Hangs indefinitely in evolve(). No output, no error, just infinite loop or hang.
Script that WORKS on ARM64
import FFPopSim as h
import numpy as np
L = 10
N = 500
pop = h.haploid_highd(L)
pop.carrying_capacity = N
pop.outcrossing_rate = 1
# NO crossover_rate or mutation_rate set
initial_af = 0.5 * np.ones(L)
pop.set_allele_frequencies(initial_af, N)
# Works fine without mutation/crossover rates:
pop.evolve(10)
print("SUCCESS!")
Result on ARM64: Completes successfully.
Test Matrix
| crossover_rate |
mutation_rate |
set_allele_frequencies |
Result on ARM64 |
| ❌ Not set |
❌ Not set |
✅ Called |
✅ Works |
| ✅ Set |
❌ Not set |
✅ Called |
❌ Hangs |
| ❌ Not set |
✅ Set |
✅ Called |
❌ Hangs |
| ✅ Set |
✅ Set |
✅ Called |
❌ Hangs |
| ✅ Set |
✅ Set |
❌ Not called |
✅ Works |
Key Findings
- Size-independent: The hang occurs even with tiny parameters (L=10, N=500)
- set_allele_frequencies() is the trigger: Setting rates before
set_allele_frequencies() causes the subsequent evolve() to hang
- x86_64 appears unaffected: Ubuntu x86_64 CI passes all tests including
genetic_drift.py
- Either rate causes the issue: Both
crossover_rate and mutation_rate independently trigger the hang
Affected Examples
The examples/genetic_drift.py example is affected by this issue on ARM64 as it sets both rates before calling set_allele_frequencies().
Impact
- ARM64 macOS users cannot use
crossover_rate or mutation_rate with set_allele_frequencies()
- Affects macOS 15 ARM64 CI builds
- Does not appear to affect Intel/x86_64 builds
- Prevents running realistic population genetics simulations on Apple Silicon
Possible Causes
- ARM64-specific code generation issue in evolution loop with recombination/mutation
- Incorrect loop termination condition only triggered on ARM64
- Memory ordering or atomics issue with ARM64 architecture
- Interaction between
set_allele_frequencies() internal state and mutation/recombination code paths
Workaround
For ARM64 users, avoid setting crossover_rate or mutation_rate when using set_allele_frequencies(). Use set_wildtype() instead if mutation/recombination are needed.
Description
haploid_highd.evolve()hangs indefinitely on ARM64 (Apple Silicon) whencrossover_rateormutation_rateare set before callingset_allele_frequencies(). This appears to be an ARM64-specific issue, as x86_64 CI tests pass successfully.Environment
Root Cause
The hang occurs when:
crossover_rateORmutation_rate(or both)set_allele_frequencies()evolve()Reproduction
Script that HANGS on ARM64
Result on ARM64: Hangs indefinitely in
evolve(). No output, no error, just infinite loop or hang.Script that WORKS on ARM64
Result on ARM64: Completes successfully.
Test Matrix
Key Findings
set_allele_frequencies()causes the subsequentevolve()to hanggenetic_drift.pycrossover_rateandmutation_rateindependently trigger the hangAffected Examples
The
examples/genetic_drift.pyexample is affected by this issue on ARM64 as it sets both rates before callingset_allele_frequencies().Impact
crossover_rateormutation_ratewithset_allele_frequencies()Possible Causes
set_allele_frequencies()internal state and mutation/recombination code pathsWorkaround
For ARM64 users, avoid setting
crossover_rateormutation_ratewhen usingset_allele_frequencies(). Useset_wildtype()instead if mutation/recombination are needed.