原生 Fortran 后端(HASH-HP)
CNCHASH 基于 Modern Fortran + OpenMP 后端构建。所有数值计算(网格搜索、
S/P 振幅、不确定性分析、速度模型表)都在 libhashhp 中运行;Python
层负责 API、文件处理和批量调度。如果没有编译原生库,包会给出明确的
构建错误。
架构
HASH_complete/ # 原始 Fortran HASH v1.2(不可变上游,golden reference)
cnchash/ # Python 包
├── backend/
│ ├── base.py # HashBackend 接口
│ └── fortran_backend.py # libhashhp 的 ctypes 绑定
├── driver.py # run_hash / run_hash_batch
├── io.py # 震相/台站文件处理
└── utils.py # 纯 Python 工具
src/hash_hp/ # Modern Fortran 核心
├── hash_kinds.f90 # real64/int32 类型定义
├── hash_geometry.f90 # TO_CAR/FPCOOR/cross
├── hash_rotation.f90 # 旋转网格缓存
├── hash_runtime.f90 # 网格缓存 + OpenMP 线程控制
├── hash_focalmc.f90 # FOCALMC,旋转方向 OpenMP 并行
├── hash_misfit.f90 # GET_GAP/GET_MISF
├── hash_uncertainty.f90# MECH_ROT/MECH_AVG/MECH_PROB
├── hash_amplitude.f90 # FOCALAMP_MC/GET_MISF_AMP
├── hash_velocity.f90 # LAYERTRACE/MK_TABLE/GET_TTS
├── hash_batch.f90 # 完整事件流水线 + 事件级并行批处理
└── hash_c_api.f90 # 稳定的 ISO_C_BINDING ABI(ctypes,无需 f2py)
设计规则
内核无 I/O。
src/hash_hp只接收数组并返回数组;文件、格式和 异常都由 Python 处理。热循环零分配。 每个事件的 workspace 复用;旋转网格每个
dang只构建一次,之后共享只读。禁止嵌套 OpenMP。 批量模式要么按事件并行、要么按旋转并行,绝不 同时嵌套。
默认确定性。 可接受机制按网格顺序取前
maxout个 (selection=0)。传入selection=1可复现原始 HASH 的随机选择。默认不开
-ffast-math。 科学计算正确性优先;如需开启显式设置CNCHASH_FAST_MATH=ON。HASH_complete/保持不动。 它是 golden reference。
构建
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
默认为可移植构建。设置 -DCNCHASH_NATIVE_MARCH=ON 可生成仅在当前
机器上运行、约快 2.5 倍的本机优化版本。
后端选择
from cnchash import run_hash, available_backends, get_backend_info
run_hash(az, the, pol, qual, backend="auto") # 默认(fortran)
run_hash(az, the, pol, qual, backend="fortran") # 显式指定
print(available_backends())
print(get_backend_info())
环境变量:CNCHASH_BACKEND、CNCHASH_NUM_THREADS、
CNCHASH_HASHHP_LIB(显式指定库路径)。
批量模式
run_hash_batch 一次调用将大量事件送入 Fortran 核心(CSR 风格扁平
数组),大型目录使用事件级 OpenMP 并行:
from cnchash import run_hash_batch
results = run_hash_batch(events, nmc=30, backend="fortran", num_threads=16)
与 HASH v1.2 的有意差异
项目 |
HASH v1.2 |
HASH-HP |
|---|---|---|
GET_GAP 空隙 |
INTEGER(隐式类型截断) |
REAL(空隙为连续值) |
GET_MISF 断层面向量 |
弧度被误当作度数(单位 bug) |
已修复:向 FPCOOR 传度数 |
GET_MISF_AMP stdr |
振幅台站累计权重 |
相同 |
nf > maxout 时的选择 |
|
默认确定性 |
velocity GET_TTS 深度检查 |
|
|
velocity 射线缓冲区 |
固定 10001(可能溢出) |
20001 堆分配 |
所有差异都是 bug 修复。测试保证可接受机制集合和首选解在相同输入下 与原始 HASH v1.2 一致(见 tests/test_accuracy.py),仅剩聚类边界上 单精度与双精度带来的微小差异。