engine-cuda: native CUDA mining engine behind MinerEngine #16

Merged
grenade merged 1 commits from cuda/engine-skeleton into main 2026-09-03 11:57:42 +00:00
Owner

Implements #3 steps 1 through 3 in one go: crate, straight port of the kernel, and the __umul64hi field multiply. Nothing in engine-gpu is touched.

What changed

  • crates/engine-cuda (lair-owned): CudaEngine behind MinerEngine, same batch loop, cancellation, thread-local device assignment, metrics (kernel label cuda) and stale accounting as the wgpu engine. cudarc 0.19 with dynamic loading, so there is no link-time CUDA dependency and the binary runs on hosts without a driver (it just falls back).
  • kernels/mining.cu: same host contract and sponge schedule as mining_u64.wgsl (host midstate, low-256-bit nonce increments, lazy second squeeze), bit-exact with pow_core. The field multiply is __umul64hi plus a plain multiply and one reduction instead of four 32-bit partials with carry reconstruction.
  • build.rs: generates poseidon2_constants.cuh from qp-poseidon-constants (the rule from #1: a hash change at origin is a dependency bump, never a hand-copied table) and compiles one fat binary with cubins for sm_86, sm_89, sm_120 plus compute_120 PTX when nvcc is present. Without nvcc (the rust lint runner, workstations) it writes an empty image and warns; the crate still builds and try_new fails with a clear message.
  • miner-service: resolve_gpu_configuration tries CUDA first unless --gpu-engine wgpu; --gpu-engine cuda makes its absence an error. miner-cli gains the flag (MINER_GPU_ENGINE) on serve and benchmark. Worker exit clears CUDA resources too.
  • bench-harness: --engine auto|cuda|wgpu.
  • deploy.yaml: matrix rows carry the kernel validate expects on miner_device_hashes_total; a silent wgpu fallback on a CUDA host now fails the deploy.

Measured

quadbrat, RTX 3060 at 130 W, miner paused, 2 x 10 s windows:

engine MH/s parity
wgpu (u64 kernel) 37.3 5/5
CUDA 59.5 5/5

1.59x from the straight port. Grid sizing sweep (MINER_CUDA_THREADS_PER_SM): 8192 and above are flat at 59.4; 2048 loses 10 percent. The bench workflow on this PR runs --engine auto, so its comment below is the 4090 number against the 144.4 MH/s wgpu baseline.

clippy -D warnings, fmt and workspace tests clean (with the empty-kernel build here; the kernel built and passed parity on quadbrat).

What merging does

The deploy builds on cuda-13.0, where nvcc is present, so the fat binary is embedded and both hosts switch to the CUDA engine on this merge; validate asserts kernel="cuda" on device 0.

Not yet: __constant__/unroll tuning and pipelined submission (steps 5 and 6 of #3), sccache.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CBgs2nSi4H2mdh8kD8vMX5

Implements #3 steps 1 through 3 in one go: crate, straight port of the kernel, and the `__umul64hi` field multiply. Nothing in `engine-gpu` is touched. ## What changed - **`crates/engine-cuda`** (lair-owned): `CudaEngine` behind `MinerEngine`, same batch loop, cancellation, thread-local device assignment, metrics (kernel label `cuda`) and stale accounting as the wgpu engine. `cudarc` 0.19 with dynamic loading, so there is no link-time CUDA dependency and the binary runs on hosts without a driver (it just falls back). - **`kernels/mining.cu`**: same host contract and sponge schedule as `mining_u64.wgsl` (host midstate, low-256-bit nonce increments, lazy second squeeze), bit-exact with `pow_core`. The field multiply is `__umul64hi` plus a plain multiply and one reduction instead of four 32-bit partials with carry reconstruction. - **`build.rs`**: generates `poseidon2_constants.cuh` from `qp-poseidon-constants` (the rule from #1: a hash change at origin is a dependency bump, never a hand-copied table) and compiles one fat binary with cubins for `sm_86`, `sm_89`, `sm_120` plus `compute_120` PTX when nvcc is present. Without nvcc (the `rust` lint runner, workstations) it writes an empty image and warns; the crate still builds and `try_new` fails with a clear message. - **`miner-service`**: `resolve_gpu_configuration` tries CUDA first unless `--gpu-engine wgpu`; `--gpu-engine cuda` makes its absence an error. `miner-cli` gains the flag (`MINER_GPU_ENGINE`) on `serve` and `benchmark`. Worker exit clears CUDA resources too. - **`bench-harness`**: `--engine auto|cuda|wgpu`. - **`deploy.yaml`**: matrix rows carry the kernel validate expects on `miner_device_hashes_total`; a silent wgpu fallback on a CUDA host now fails the deploy. ## Measured quadbrat, RTX 3060 at 130 W, miner paused, 2 x 10 s windows: | engine | MH/s | parity | | --- | --- | --- | | wgpu (u64 kernel) | 37.3 | 5/5 | | CUDA | 59.5 | 5/5 | **1.59x** from the straight port. Grid sizing sweep (`MINER_CUDA_THREADS_PER_SM`): 8192 and above are flat at 59.4; 2048 loses 10 percent. The bench workflow on this PR runs `--engine auto`, so its comment below is the 4090 number against the 144.4 MH/s wgpu baseline. clippy `-D warnings`, fmt and workspace tests clean (with the empty-kernel build here; the kernel built and passed parity on quadbrat). ## What merging does The deploy builds on `cuda-13.0`, where nvcc is present, so the fat binary is embedded and both hosts switch to the CUDA engine on this merge; validate asserts `kernel="cuda"` on device 0. Not yet: `__constant__`/unroll tuning and pipelined submission (steps 5 and 6 of #3), `sccache`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01CBgs2nSi4H2mdh8kD8vMX5
grenade added 1 commit 2026-09-03 11:52:35 +00:00
engine-cuda: native CUDA mining engine behind MinerEngine
All checks were successful
ci / fmt (pull_request) Successful in 20s
bench / build (pull_request) Successful in 1m15s
ci / clippy (pull_request) Successful in 1m40s
ci / doc (pull_request) Successful in 2m6s
bench / measure (pull_request) Successful in 2m51s
ci / test (pull_request) Successful in 7m45s
6ecc5ee6c7
quantus/miner#3. New crate, nothing in engine-gpu touched.

- kernels/mining.cu: the same host contract and sponge schedule as
  mining_u64.wgsl (host midstate, low-256-bit nonce increments, lazy second
  squeeze), bit-exact with pow_core. The field multiply is __umul64hi plus a
  plain multiply and one reduction, instead of four 32-bit partials with
  carry reconstruction.
- build.rs: generates poseidon2_constants.cuh from qp-poseidon-constants
  (a hash change at origin is a dependency bump, never a hand-copied table)
  and, when nvcc is present, compiles one fat binary with cubins for
  sm_86/89/120 plus compute_120 PTX. Without nvcc it writes an empty image,
  the crate still builds, and CudaEngine::try_new fails with a clear message
  so the miner falls back to wgpu.
- lib.rs: CudaEngine with the same batch loop, cancellation, thread-local
  device assignment, metrics (kernel label "cuda") and stale accounting as
  engine-gpu. cudarc 0.19 with dynamic loading; no link-time CUDA dependency.
- miner-service: resolve_gpu_configuration tries CUDA first unless
  --gpu-engine wgpu; --gpu-engine cuda makes its absence an error.
  miner-cli gains the flag on serve and benchmark (MINER_GPU_ENGINE).
- bench-harness: --engine auto|cuda|wgpu.
- deploy.yaml: matrix rows carry the kernel validate expects; a wgpu
  fallback on a CUDA host now fails the deploy instead of passing at a
  fraction of the hashrate.

Measured on quadbrat (RTX 3060, 130 W, miner paused, 2 x 10 s windows,
parity 5/5 verified against CPU): wgpu 37.3 MH/s, CUDA 59.5 MH/s (1.59x).
Grid sizing 8192 threads/SM or more is flat; 2048 loses 10%.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CBgs2nSi4H2mdh8kD8vMX5

quantus-bench 6ecc5ee6c7 on benjy.hanzalova.internal

worker median MH/s spread windows
0 297.70 0.1% 297.5, 297.7, 297.8, 297.8, 297.5

total median: 297.70 MH/s (batch 1000000, 5 x 30s, engine gpu-cuda)

  • gpu 0 NVIDIA GeForce RTX 4090: driver 580.173.02, limit 250 W, draw 250 W, sm 1935 MHz, 58 C
  • parity: OK (25/25 jobs found solutions, all verified against CPU)
    --- resume miner ---
    active
## quantus-bench 6ecc5ee6c7ac708519e2e348d563bdf3f3a45124 on benjy.hanzalova.internal | worker | median MH/s | spread | windows | | --- | --- | --- | --- | | 0 | 297.70 | 0.1% | 297.5, 297.7, 297.8, 297.8, 297.5 | total median: **297.70 MH/s** (batch 1000000, 5 x 30s, engine gpu-cuda) - gpu 0 NVIDIA GeForce RTX 4090: driver 580.173.02, limit 250 W, draw 250 W, sm 1935 MHz, 58 C - parity: OK (25/25 jobs found solutions, all verified against CPU) --- resume miner --- active
grenade merged commit d5e72d6a15 into main 2026-09-03 11:57:42 +00:00
grenade deleted branch cuda/engine-skeleton 2026-09-03 11:57:43 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: blackbeard/miner#16