Ottimizza il kernel GPU: ~2x throughput sulla Quadro P4000

Tre modifiche, tutte a parità di risultato (verificate end-to-end):

- Ammortamento della moltiplicazione scalare: prima scalar_mult_basic
  (l'operazione di gran lunga più costosa) veniva rieseguita a ogni
  batch, cioè 40 volte per kernel launch. Ora viene eseguita UNA sola
  volta per launch; il punto base P0 viene poi fatto avanzare di
  GPU_EC_BATCH_SIZE*G a ogni round con una semplice addizione EC
  affine, ripiegata nella batch inversion già presente (nuovo slot
  NEXT negli array Zj/prefix). La scalar mult è così ammortizzata su
  ~5120 chiavi invece di 128.

- Una sola inversione di campo per round invece di due: la
  normalizzazione del nuovo P0 condivide l'inversione di Montgomery
  del batch.

- Inversione modulare tramite la catena di addizione di libsecp256k1
  (255 quadrati + 15 moltiplicazioni) al posto del quadrato-e-moltiplica
  ingenuo (~256 + ~128). Rimosso il vecchio modinv_fermat e la costante
  FIELD_P_MINUS_2 non più usata.

- Rimosso l'array locale invZ[] (passaggio all'indietro fuso con la
  conversione affine + match), riducendo la memoria locale per-thread e
  migliorando l'occupancy.

Misurato nello stesso ambiente/scheda: 15.0M -> ~30M keys/sec.
Correttezza verificata end-to-end con privkey nota a offset 0, 50, 127,
128 (avanzamento del punto base), 200 e 5119 (40 avanzamenti
consecutivi): tutte trovate con la chiave privata corretta. Nessun
falso positivo su chiave pubblica valida casuale.
This commit is contained in:
2026-07-03 16:26:40 +02:00
parent ac68b6aa88
commit fabefbbb6a
3 changed files with 130 additions and 76 deletions
+2 -1
View File
@@ -63,7 +63,8 @@ There is no test suite in this repo.
### `bruteforce/p2pk_bruteforce_gpu.cu` (GPU, CUDA, single file)
- Same algorithmic strategy as the CPU version (Jacobian batch add + Montgomery batch inversion), but GMP doesn't run on-device, so 256-bit field arithmetic mod the secp256k1 prime is hand-written (`u256` = 4×uint64 limbs, schoolbook multiply via `unsigned __int128`, fast reduction using `2^256 ≡ 2^32+977 (mod p)`). Verified bit-for-bit against `secp256k1_ec_pubkey_create` before trusting it (see conversation/test methodology — no separate test file is checked in).
- Each CUDA thread is an independent search lane (own random starting privkey, own local batch state), same as a CPU thread — just thousands of them instead of ~11. Per-thread batch size is `GPU_EC_BATCH_SIZE` (128), smaller than the CPU's 256, to keep per-thread local-memory footprint (Jacobian batch arrays) bounded across tens of thousands of concurrent threads.
- Scalar multiplication on-device is plain double-and-add (no wNAF/windowing/precomputed tables like libsecp256k1 has on CPU) — the main further-optimization opportunity if more speed is needed.
- Scalar multiplication (`scalar_mult_basic`, plain double-and-add) runs **once per kernel launch**, not once per batch: the base point P0 is then advanced by `GPU_EC_BATCH_SIZE·G` each round via a cheap affine EC add folded into the batch inversion (the `NEXT` slot in the Zj/prefix arrays), so the expensive scalar mult is amortized over all `GPU_OUTER_ITERS_PER_LAUNCH × GPU_EC_BATCH_SIZE` keys. There is exactly one field inversion per round (Montgomery batch trick), done with the libsecp256k1 addition-chain `modinv` (255 sqr + 15 mul), not naive square-and-multiply.
- Remaining optimization headroom: double-and-add scalar mult (no wNAF/windowing), schoolbook `mulmod`, and occupancy tuning (grid size / batch size vs per-thread local memory).
- Host side still uses libsecp256k1 (CPU) only for one-time setup: precomputing G-multiples and validating/loading target keys into a host-sorted array + Bloom filter, both uploaded once to device memory. Device-side matching = Bloom filter check + binary search over the sorted target array.
- `NVCC_ARCH` in the Makefile defaults to `sm_61` (Pascal) — must match the actual GPU (`make gpu-info` shows compute capability via `nvidia-smi`, then pick the matching `sm_XX`).
- On WSL2, the NVIDIA driver comes from the Windows host (visible as `nvidia-smi` working out of the box) — only the CUDA Toolkit needs installing inside WSL, never a driver.