Hashcat 海光 DCU
HIP 后端适配与性能对比
面向 DTK 25.04.2、HIP 6.3.25422 与 gfx936/BW DCU 的 ABI 兼容适配、构建方法、功能验证及 OpenCL 基线对比。
1. 执行摘要
hashcat v7.1.2 已包含 HIP 后端,但其内置 HIP ABI 与海光 DTK 25.04.2 的 libgalaxyhip.so 存在版本差异,设备初始化流程因而无法完成。本次适配增加显式、可选的 DTK_HIP=1 构建模式,对齐设备属性枚举与 hipDeviceProp_t 布局,并调整 DTK 动态库的退出生命周期。验证结果表明,适配后的 HIP 后端可完成设备枚举、HIPRTC 内核编译、实际任务运行、benchmark 及正常退出。
2. 测试环境与产物
软件环境
- Hashcat:
v7.1.2 - DTK:
25.04.2 - HIP:
6.3.25422 - OpenCL:
OpenCL 2.1s C-3000-APP (3452.0) - 内核:
5.10.134-17.1.3.sga8.x86_64 - 系统:Sugon OS 8.9
硬件环境
- 测试节点:
<compute-node>(名称已脱敏) - DCU 名称:
BW - ISA:
gfx936:sramecc+:xnack- - 设备类型:
HCU - 计算单元:
80 - 显存:
65520 MB - 核心频率:
1500 MHz
最终二进制
| 用途 | 路径 | 大小 | SHA-256 |
|---|---|---|---|
| DTK HIP 适配版 | hashcat-hip-dtk | 1,332,656 B | be0b2201c913828488dfe07ce64eef3f481c97ae4cfe41d4af8ffc1549df1e36 |
| OpenCL 基线版本 | hashcat-opencl-original | 1,332,656 B | a25c3b28ad1c980aef71457ff0cc7d367dd0e4165ab2dc6ac9d20fcb48208994 |
二进制示例路径为 /path/to/hashcat/。OpenCL 基线版本单独保留,以便开展回归验证与性能对比。
3. 兼容性现象与原因分析
3.1 登录节点与计算节点的区别
登录节点未提供 /dev/kfd,因此该环境仅适合检查二进制中的 HIP 符号,不具备设备运行验证条件。进入已分配的 DCU 计算节点后,rocminfo、hy-smi 与 OpenCL 均可正常识别设备。
rocminfo:
Name: gfx936
Marketing Name: BW
Device Type: HCU
Compute Unit: 80
3.2 适配前的 HIP 初始化现象
./hashcat -II --backend-ignore-cuda --backend-ignore-opencl
hashcat (v7.1.2) starting in backend information mode
hipDeviceGetAttribute(): invalid argument
No devices found/left.
同一环境下 OpenCL 能够识别 BW 设备,可据此排除硬件、任务分配、驱动和设备权限等基础因素,并将分析范围收敛至 hashcat HIP 主机侧 API 兼容层。
3.3 ABI 差异
hashcat 为保持动态加载能力,在 include/ext_hip.h 内复制了 HIP 类型定义,而不是编译时直接依赖系统 HIP 头文件。hashcat v7.1.2 内置定义来自更新的 ROCm ABI;DTK 25.04.2 的 hip_runtime_defines.h 使用不同的旧版布局。
| DTK 属性 | DTK 25.04.2 数值 | 用途 |
|---|---|---|
hipDeviceAttributeMaxThreadsPerBlock | 18 | 最大线程块 |
hipDeviceAttributeMaxSharedMemoryPerBlock | 25 | 共享内存 |
hipDeviceAttributeTotalConstantMemory | 26 | 常量内存 |
hipDeviceAttributeWarpSize | 27 | Wave/Warp 宽度 |
hipDeviceAttributeClockRate | 29 | 设备时钟 |
hipDeviceAttributeMultiprocessorCount | 32 | 计算单元数量 |
hipDeviceAttributeComputeCapabilityMajor/Minor | 36 / 37 | 计算能力 |
hipDeviceAttributePciBusId/PciDeviceId | 39 / 40 | PCI 地址 |
hipDeviceAttributeIntegrated | 42 | 统一内存判断 |
hipDeviceAttributeKernelExecTimeout | 79 | 内核超时属性 |
辅助探测程序还确认 DTK 的 sizeof(hipDeviceProp_t) = 792,关键字段偏移包括:totalGlobalMem=256、regsPerBlock=272、warpSize=276、clockRate=308、major=328、multiProcessorCount=336、gcnArchName=396。这与 hashcat 原定义明显不同。
4. 代码修改说明
实现遵循“默认构建行为保持不变、DTK 适配显式启用”的原则,改动集中在构建入口、HIP 类型定义、设备属性初始化、动态加载与适配说明文档。
新增 DTK_HIP ?= 0。只有执行 make DTK_HIP=1 时才定义 HC_HIP_DTK,普通构建仍使用原始 ROCm ABI。
DTK_HIP ?= 0
ifeq ($(DTK_HIP),1)
CFLAGS += -DHC_HIP_DTK
endif
在 HC_HIP_DTK 条件分支下显式定义 hashcat 实际使用的 DTK 属性编号。原始完整枚举保留在 #else 分支,不影响默认 ROCm 构建。
按 DTK 25.04.2 的字段顺序重建 hipDeviceProp_t,保证 hipGetDeviceProperties() 写入的内存布局与 hashcat 读取方式一致,尤其是 regsPerBlock、gcnArchName 等字段。
DTK 旧版结构没有 regsPerMultiprocessor 字段,而且属性编号 69 的运行时查询返回 hipErrorInvalidValue。DTK 分支使用已验证可用的 prop.regsPerBlock 作为保守兼容值。
#if defined (HC_HIP_DTK)
device_param->regsPerMultiprocessor = prop.regsPerBlock;
#else
device_param->regsPerMultiprocessor = prop.regsPerMultiprocessor;
#endif
诊断日志同时输出设备编号和属性编号,便于将运行时状态定位到具体 ABI 项;并校正 hipGetDeviceProperties 对应的日志标识。
hipDeviceGetAttribute(dev=0, attrib=69): invalid argument
DTK 的 HIP/HIPRTC DSO 注册了 C++ 退出回调。hashcat 提前 dlclose() 后,libstdc++ 在进程退出阶段仍调用这些回调,导致跳转到已卸载地址。DTK 构建因此不提前关闭这两个 DSO,交由操作系统在进程终止时回收。
构建产物不纳入版本控制,并补充构建、验证与版本边界说明;OpenCL 基线版本单独保存,用于回归验证和性能对比。
5. 调试过程与关键转折
- 确认二进制包含 HIP:检查到
hipInit、hipDeviceGetAttribute、hiprtcCompileProgram等符号,以及--backend-ignore-hip参数。 - 排除无卡节点误判:登录节点缺少
/dev/kfd;切换到已分配的计算节点后,DCU 与驱动均正常。 - 建立 OpenCL 基线:原始二进制可通过 OpenCL 识别 BW,并完成 MD5 benchmark,证明硬件与 hashcat 核心功能正常。
- 增强日志后锁定枚举:首个失败属性从不透明的错误变为
attrib=69,随后使用 DTK 头文件编译探测程序逐项核对数值和结构偏移。 - 第一次 ABI 修复:同步属性枚举与结构体后,设备枚举推进到寄存器属性;运行时确认属性 69 不受 DTK 支持。
- 寄存器兼容处理:辅助程序显示
prop.regsPerBlock=196608,而属性 69 返回错误,因此采用该值作为保守兼容数据。 - HIP 设备枚举成功:hashcat 能显示 HIP 6.3.25422、BW、80 MCU、65520 MB 和 PCI 地址。
- HIPRTC 验证:MD5 与 NTLM benchmark 成功,证明
gfx936的运行时编译、module 加载和 kernel launch 链路可用。 - 发现退出阶段 SIGSEGV:计算结果已经输出,但退出码为 139。使用 GDB 定位到 libstdc++ 的
atexit_thread.cc:75,栈顶为无符号的已卸载地址。 - 修复 DSO 生命周期:DTK 分支保留 HIP/HIPRTC DSO 到进程退出,随后 benchmark 退出码恢复为 0。
- 正确性验证:实际 MD5 字典攻击通过 self-test,并恢复
e11c594e6a2f4eb499cceadfca988595:13LEXON。
GDB 关键回溯
Thread 1 "hashcat-hip-dtk" received signal SIGSEGV
0x000015552f2620e0 in ?? ()
#0 0x000015552f2620e0 in ?? ()
#1 (anonymous namespace)::run
at libstdc++-v3/libsupc++/atexit_thread.cc:75
#2 __run_exit_handlers () from /lib64/libc.so.6
#3 exit () from /lib64/libc.so.6
该回溯与“动态库已卸载,但退出处理器仍保留函数地址”一致。修改 DSO 生命周期后,同一测试正常退出,验证了判断。
6. Git 与编译过程
6.1 Git 建档
为保证适配过程可追溯,可先建立源码基线,再在独立分支记录 DTK HIP 适配变更。以下命令展示一种参考流程。
cd /path/to/hashcat
git init -b dtk-hip-adaptation
git add -A
git commit -m "baseline: import hashcat 7.1.2 source tree"
# 完成修改与验证后
git add .gitignore include/ext_hip.h src/Makefile \
src/backend.c src/ext_hip.c src/ext_hiprtc.c \
docs/dtk-hip-adaptation.md
git commit -m "feat: adapt HIP backend for DTK 25.04.2"
| 提交 | 说明 |
|---|---|
cb48d9d | Hashcat v7.1.2 源码树基线 |
提交标识已脱敏 | DTK 25.04.2 HIP 后端适配 |
6.2 编译步骤
DTK_HIP=1 构建之间切换时,应执行 make clean,避免复用 ABI 配置不同的对象文件。
cd /path/to/hashcat
# 保留原始二进制
cp -p hashcat hashcat-opencl-original
# 清理并构建 DTK 专用版本
make clean
make DTK_HIP=1 ENABLE_LTO=0
mv hashcat hashcat-hip-dtk
# 基本检查
./hashcat-hip-dtk --version
sha256sum hashcat-hip-dtk hashcat-opencl-original
ENABLE_LTO=0 用于降低适配调试期间的链接复杂度并保持构建可预测性。核心适配由 DTK_HIP=1 启用。
6.3 在 DCU 节点验证
ssh <compute-node>
cd /path/to/hashcat
# 只启用 HIP
./hashcat-hip-dtk -II \
--backend-ignore-cuda \
--backend-ignore-opencl
# 只启用 OpenCL
./hashcat-opencl-original -II \
--backend-ignore-cuda \
--backend-ignore-hip
7. 功能与正确性验证
| 验证项 | 命令/方式 | 结果 |
|---|---|---|
| HIP 设备枚举 | -II --backend-ignore-cuda --backend-ignore-opencl | 通过 |
| HIPRTC 优化内核 | MD5 benchmark | 通过 |
| MD5 benchmark | -b -m 0 | 39342.9 MH/s |
| NTLM benchmark | -b -m 1000 | 63283.5 MH/s |
| Self-test | MD5 字典实际攻击 | 通过 |
| 破解结果 | example0.hash + example.dict | 恢复 13LEXON |
| 资源释放与退出 | benchmark 后检查进程退出码 | 退出码 0 |
./hashcat-hip-dtk -m 0 -a 0 example0.hash example.dict \
--backend-ignore-cuda --backend-ignore-opencl \
--potfile-disable --restore-disable
Recovered:
e11c594e6a2f4eb499cceadfca988595:13LEXON
该字典测试的最终状态码为 1:输入包含 6494 个哈希,小字典耗尽时恢复其中 1 个。self-test 与目标恢复均成功,因此该状态码反映任务完成条件,而非 HIP 后端异常。
8. HIP 与 OpenCL 性能对比
8.1 测试方法
为了避免短 benchmark 隐藏热稳定和持续调度差异,采用 SHA2-256 的 8 位全字符集暴力攻击,密钥空间为 95^8 = 6,634,204,312,890,625。使用不易命中的目标哈希保证 DCU 持续满载,每个后端运行约 45 秒,并通过 hy-smi 每 2 秒采样功耗、温度和利用率。
# HIP
./hashcat-hip-dtk -m 1400 -a 3 \
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \
'?a?a?a?a?a?a?a?a' -O -w 3 --runtime 45 \
--status --status-timer 5 --potfile-disable --restore-disable \
--backend-ignore-cuda --backend-ignore-opencl
# OpenCL:攻击参数相同,只切换后端和二进制
./hashcat-opencl-original -m 1400 -a 3 \
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \
'?a?a?a?a?a?a?a?a' -O -w 3 --runtime 45 \
--status --status-timer 5 --potfile-disable --restore-disable \
--backend-ignore-cuda --backend-ignore-hip
8.2 核心结果
| 指标 | HIP | OpenCL | 解读 |
|---|---|---|---|
| 平均速度(10 个状态样本) | 5913.79 MH/s | 5913.48 MH/s | HIP 约 +0.005%,无实际差异 |
| 最终稳定速度 | 5914.3 MH/s | 5913.8 MH/s | 差异小于 0.01% |
| 速度范围 | 5911.5–5914.3 | 5910.4–5914.0 | 波动均很小 |
| 满载平均功耗 | 368.8 W | 369.7 W | 差 0.9 W,在采样波动内 |
| 满载功耗范围 | 365–369 W | 367–370 W | 基本一致 |
| 平均温度 | 61.0°C | 61.1°C | 基本一致 |
| 最高温度 | 61°C | 62°C | 无显著差异 |
| 平均利用率 | 100% | 100% | 均达到满载 |
| Host memory | 8173 MB | 6132 MB | HIP 多使用约 2041 MB |
| 运行结束状态 | Runtime 到期 | Runtime 到期 | 均按预期停止 |
速度可视化
横条按 5914.1 MH/s 归一化。两者肉眼不可区分,符合数值差异低于 0.01% 的结论。
8.3 自动调优与资源差异
| 调度参数 | HIP | OpenCL |
|---|---|---|
| Accel | 6 | 27 |
| Loops | 1024 | 1024 |
| Threads | 1024 | 256 |
| Vector width | 1 | 1 |
| 单次调度时间 | 84.95 ms | 95.55 ms |
| Preferred thread multiple | 64 | 32 |
两个后端选择了不同的工作组和加速组合,但最终吞吐一致,说明两条路径均能充分利用该 DCU。HIP 的主机内存占用明显更高,是本次测试中最明确的资源差异。
8.4 累计进度为何不直接比较
最终记录的 HIP 进度为 266,757,734,400,OpenCL 为 270,092,206,080。OpenCL 看似高约 1.25%,但其最终状态落在约 46 秒,而 HIP 为约 45 秒;初始化、状态刷新和 runtime 停止边界也不完全相同。因此报告以 hashcat 的 10 个持续速度样本作为主比较依据,而不以累计进度得出性能结论。
9. 结论、建议与已知限制
可用性
HIP 设备枚举、HIPRTC、内核加载、实际破解和正常退出均已通过,最小适配目标完成。
性能
在本次 SHA2-256 测试中,HIP 与 OpenCL 均约为 5.914 GH/s,差异不足 0.01%;当前数据未体现显著性能差异。
应用建议
在扩大算法覆盖和稳定性验证前,OpenCL 可作为现有基线;HIP 版本适用于功能验证及后续 gfx936 定向优化。
已知限制
- 适配以 DTK 25.04.2 / HIP 6.3.25422 为验证基线。升级 DTK 后应重新核对枚举值、结构体大小和字段偏移。
- 当前验证覆盖代表性的 MD5、NTLM 与 SHA2-256 路径,结论不扩展至未经测试的 hash-mode。
regsPerMultiprocessor使用保守兼容值;当前算法运行正常,但可能影响某些内核的调优上限。- DTK 构建故意不提前
dlcloseHIP/HIPRTC DSO。这不会造成进程生命周期之外的泄漏,但与标准 hashcat 的卸载行为不同。 - 45 秒测试适合比较稳定吞吐,不等同于数小时或数天的长期可靠性测试。
后续建议
- 按常用工作负载扩展测试:
-m 1000、-m 10900、-m 22000、-m 3200。 - 对 HIP 和 OpenCL 分别执行 1–4 小时稳定性测试,监控温度、功耗、驱动日志和错误计数。
- 为 DTK ABI 增加自动化探测或编译期断言,避免 DTK 升级后静默使用错误布局。
- 如果目标是获得性能提升,应进一步分析 HIPRTC 编译参数、寄存器占用、wavefront 行为和专用 tuning,而不是仅切换后端。
10. 附录:复现与审计命令
查看代码变更
cd /path/to/hashcat
git status
git log --oneline --decorate -5
git show --stat 7ef6f77
git show 7ef6f77
重新构建
make clean
make DTK_HIP=1 ENABLE_LTO=0
mv hashcat hashcat-hip-dtk
基本验证
ssh <compute-node>
cd /path/to/hashcat
./hashcat-hip-dtk -II --backend-ignore-cuda --backend-ignore-opencl
./hashcat-hip-dtk -b -m 0 --backend-ignore-cuda --backend-ignore-opencl --runtime 10
./hashcat-hip-dtk -b -m 1000 --backend-ignore-cuda --backend-ignore-opencl --runtime 10
关键文件索引
| 文件 | 作用 |
|---|---|
src/Makefile | DTK_HIP=1 构建入口 |
include/ext_hip.h | DTK 枚举与结构体 ABI |
src/backend.c | 设备属性初始化兼容 |
src/ext_hip.c | HIP 动态加载、日志和 DSO 生命周期 |
src/ext_hiprtc.c | HIPRTC DSO 生命周期 |
docs/dtk-hip-adaptation.md | 仓库内简要适配记录 |