Skip to content

Commit b38c058

Browse files
committed
docs(cpu): document CPU mining, parameters, and GPU+CPU tuning
Update ARCHITECTURE.md and CLAUDE.md (CPU resolver = std::thread pool), document --cpu_threads/--cpu_affinity in PARAMETERS.md, add CPU_TUNING.md (thread-count/affinity guidance incl. reserving cores for the GPU), and refresh the docker build docs for the GPU/CPU axes.
1 parent fa9b377 commit b38c058

7 files changed

Lines changed: 108 additions & 20 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ Synchronization uses `AtomicCounter<uint64_t>` to signal job/memory/constant upd
108108
| `sources/device/` | `DeviceManager` singleton + `Device` base + `DeviceNvidia`/`DeviceAmd` |
109109
| `sources/resolver/amd/` | OpenCL resolvers — one per algorithm |
110110
| `sources/resolver/nvidia/` | CUDA resolvers — one per algorithm |
111-
| `sources/resolver/cpu/` | OpenMP CPU resolver |
111+
| `sources/resolver/cpu/` | CPU resolver (std::thread pool, `--cpu_threads`/`--cpu_affinity`) |
112112
| `sources/profiler/` | NVML (NVIDIA) / ADL (AMD) GPU monitoring |
113113
| `sources/statistical/` | Hashrate and share counters |
114114
| `sources/api/` | HTTP REST API (default port 8080) backed by Boost.ASIO |

documentation/ARCHITECTURE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# LuminousMiner — Architecture
22

3-
> Version 0.12 · C++20 · NVIDIA (CUDA) · AMD (OpenCL) · CPU (OpenMP)
3+
> Version 0.12 · C++20 · NVIDIA (CUDA) · AMD (OpenCL) · CPU (std::thread pool)
44
55
---
66

@@ -81,7 +81,7 @@ sources/
8181
├── resolver/
8282
│ ├── amd/ # OpenCL resolvers (one per algorithm)
8383
│ ├── nvidia/ # CUDA resolvers (one per algorithm)
84-
│ └── cpu/ # OpenMP CPU resolver
84+
│ └── cpu/ # CPU resolver (std::thread pool)
8585
├── statistical/ # Hashrate & share counters
8686
├── stratum/ # Stratum protocol implementations
8787
└── web/ # Web UI assets

documentation/CPU_TUNING.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# CPU Mining — Thread Count & Affinity Tuning
2+
3+
The CPU resolver scans nonces with a self-owned pool of persistent worker threads (one
4+
batch of nonces fanned across the pool each iteration). Three flags control it:
5+
6+
| Flag | Default | Meaning |
7+
|---|---|---|
8+
| `--cpu` | `false` | Enable the CPU device. |
9+
| `--cpu_threads` | all logical cores | Number of worker threads (pool size). |
10+
| `--cpu_affinity` | none | Hex bitmask of logical cores to pin workers to (bit *i* = core *i*). |
11+
12+
`--cpu_affinity` accepts `0xFF` or `FF` (up to 64 cores). `--cpu_threads=0` is treated as
13+
unset and falls back to all logical cores.
14+
15+
## How the two flags interact
16+
17+
| `--cpu_threads` | `--cpu_affinity` | Result |
18+
|---|---|---|
19+
| unset | unset | one worker per logical core, no pinning (default) |
20+
| unset | set | N = popcount(mask); worker *k* is pinned to the *k*-th set bit |
21+
| set | unset | N workers, no pinning |
22+
| set | set | N workers; if N > set bits → pinned round-robin over them; if N < set bits → first N |
23+
24+
## Running CPU mining alongside a GPU
25+
26+
A GPU is not autonomous: its host-side feeder thread and the OpenCL/CUDA driver threads
27+
(all inside the miner process) must launch kernels and read results continuously to keep
28+
the GPU busy. If the CPU resolver spawns **one worker per core** (the default), those
29+
workers saturate every core and starve the GPU's host threads — the GPU can drop to a
30+
fraction of its solo hashrate while the CPU adds only a tiny amount.
31+
32+
> Example (16-core host + an RX 9070 XT, BLAKE3): GPU-only ≈ **1.70 GH/s**. With default
33+
> all-core CPU mining also enabled, the GPU collapsed to ≈ **0.4 GH/s** — a far bigger
34+
> loss than the ≈ 11 MH/s of CPU gained.
35+
36+
Lowering the thread *count* alone does **not** fix this: unpinned threads roam across all
37+
cores and still bounce the GPU's feeder. The fix is to **reserve cores for the GPU with
38+
affinity**:
39+
40+
```sh
41+
# Pin the CPU pool to cores 0-7; leave cores 8-15 free for the GPU's host threads.
42+
miner --algo=blake3 --host=<pool> --port=<port> --wallet=<addr> \
43+
--amd=true --cpu=true --cpu_threads=8 --cpu_affinity=0xFF
44+
```
45+
46+
On the example host this restored the GPU to its full ≈ 1.70 GH/s while still mining
47+
≈ 7 MH/s on the CPU.
48+
49+
## Recommendations
50+
51+
- On a GPU rig, **GPU-only is usually best** — a modern GPU out-hashes the CPU by orders
52+
of magnitude, so CPU mining rarely pays for the contention it adds.
53+
- If you do want CPU hashes too, **reserve cores for the GPU** with `--cpu_threads` +
54+
`--cpu_affinity`; leave a few cores out of the CPU mask for the GPU's host/driver
55+
threads, and tune the split to taste.
56+
- On a **CPU-only** machine, the defaults (all cores, no pinning) are correct.
57+
- Process-level priority tweaks (e.g. forcing the whole miner to "below normal") do
58+
**not** relieve GPU+CPU contention — they lower the GPU feeder thread too. The
59+
reservation has to be per-core (affinity).

documentation/PARAMETERS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ N/A : No default value is set.
2626
| `--nvidia` || true | Enable or disable device nvidia. | `--nvidia=<true\|false>` |
2727
| `--amd` || true | Enable or disable device amd. | `--amd=<true\|false>` |
2828
| `--cpu` || false | Enable or disable device cpu. | `--cpu=<true\|false>` |
29+
| `--cpu_threads` || all cores | Number of CPU worker threads (pool size). | `--cpu_threads=8` |
30+
| `--cpu_affinity` || none | Hex bitmask of logical cores to pin CPU workers to (bit i = core i). See [CPU_TUNING.md](CPU_TUNING.md). | `--cpu_affinity=0xFF` |
2931
| `--socks5` || false | Enable pool connection through a SOCKS5 proxy server on localhost. | `--socks5=<true\|false>` |
3032
| `--socks_port` || 9050 | The port of the SOCKS5 proxy server on localhost. | `--socks_port=9050` |
3133
| `--socks_host` || 127.0.0.1 | The host address of the SOCKS5 proxy server. | `--socks_host=127.0.0.1` |

documentation/build/BUILD_DOCKER_LINUX.md

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,41 @@
33
Build the Linux `miner` (ELF) in a container with **no local compilers or SDKs**
44
only Docker (BuildKit) is required.
55

6-
The Dockerfile selects backends with a `GPU` build-arg (`amd` | `nvidia` | `both`,
7-
default `both`):
6+
The Dockerfile exposes two independent axes — a `GPU` build-arg
7+
(`amd` | `nvidia` | `both` | `none`, default `both`) and a `CPU` build-arg
8+
(`ON` | `OFF`, default `OFF`):
89

910
| Dockerfile | Output | Backends |
1011
|---|---|---|
11-
| `docker/Dockerfile.linux` | `miner` (ELF) | AMD, NVIDIA, or both |
12+
| `docker/Dockerfile.linux` | `miner` (ELF) | AMD, NVIDIA, both, or none — plus the CPU resolver when `CPU=ON` |
1213

13-
`GPU=amd` uses a lean `ubuntu:24.04` base; `GPU=nvidia`/`both` use
14-
`nvidia/cuda:13.1.2-devel-ubuntu24.04`.
14+
`GPU=amd`/`none` use a lean `ubuntu:24.04` base; `GPU=nvidia`/`both` use
15+
`nvidia/cuda:13.1.2-devel-ubuntu24.04`. `CPU=ON` folds the CPU resolver into
16+
the same binary and can combine with any `GPU` value. `GPU=none CPU=ON` is a CPU-only
17+
build; `GPU=none CPU=OFF` is rejected (nothing to build).
1518

1619
## Helper script (PowerShell)
1720
```powershell
18-
scripts/docker-build.ps1 -Os linux -Gpu amd # AMD-only ELF
21+
scripts/docker-build.ps1 -Os linux -Gpu amd # AMD-only ELF
22+
scripts/docker-build.ps1 -Os linux -Gpu amd -Cpu # AMD + CPU in one ELF
23+
scripts/docker-build.ps1 -Os linux -Gpu none -Cpu # CPU-only ELF
1924
```
20-
Binaries are extracted to `dist/<os>-<gpu>/` (e.g. `dist/linux-amd/`).
25+
Binaries are extracted to `dist/<os>-<gpu>[-cpu]/` (e.g. `dist/linux-amd/`,
26+
`dist/linux-amd-cpu/`, `dist/linux-none-cpu/`).
2127

2228
## Direct docker build
2329
```sh
2430
# Linux, AMD only -> dist/linux-amd/
2531
DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile.linux \
2632
--build-arg GPU=amd --target artifact -o dist/linux-amd .
33+
34+
# Linux, AMD + CPU resolver -> dist/linux-amd-cpu/
35+
DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile.linux \
36+
--build-arg GPU=amd --build-arg CPU=ON --target artifact -o dist/linux-amd-cpu .
37+
38+
# Linux, CPU-only -> dist/linux-none-cpu/
39+
DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile.linux \
40+
--build-arg GPU=none --build-arg CPU=ON --target artifact -o dist/linux-none-cpu .
2741
```
2842
The artifact contains `miner`, the OpenCL `kernel/` directory, and the required
2943
runtime files.

documentation/build/BUILD_DOCKER_LINUX_ARM64.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ On an Apple Silicon Mac the arm64 image builds and runs **natively** (no emulati
66

77
```sh
88
docker buildx build --platform linux/arm64 -f docker/Dockerfile.linux \
9-
--build-arg GPU=cpu --target runtime -t lm:linux-arm64 --load .
9+
--build-arg GPU=none --build-arg CPU=ON --target runtime -t lm:linux-arm64 --load .
1010
docker run --rm lm:linux-arm64 --help
1111
```
1212

13-
The same `GPU=cpu` mode works for x86-64 (`--platform linux/amd64`). The existing
14-
`GPU=amd|nvidia|both` GPU builds are unchanged. CI builds the arm64 image on a native
15-
arm64 runner via `.github/workflows/miner_linux_arm64_vcpkg.yml`, and the x86-64
16-
CPU path via `.github/workflows/miner_linux_x64_vcpkg.yml`.
13+
The same `GPU=none CPU=ON` (CPU-only) mode works for x86-64 (`--platform linux/amd64`).
14+
The `GPU=amd|nvidia|both` GPU builds are unchanged, and `CPU=ON` can be added to any of
15+
them to fold in the CPU resolver. CI builds the arm64 image on a native arm64 runner via
16+
`.github/workflows/miner_linux_arm64_vcpkg.yml`, and the x86-64 CPU path via
17+
`.github/workflows/miner_linux_x64_vcpkg.yml`.

documentation/build/BUILD_DOCKER_WINDOWS.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,36 @@ Build a Windows `miner.exe` (PE32+) with **no local compilers or SDKs** — only
55
(clang-cl + xwin), so Docker stays in **Linux container mode**; there is no engine-mode
66
switch and no Windows host needed.
77

8-
The Dockerfile selects backends with a `GPU` build-arg (`amd` | `nvidia` | `both`,
9-
default `both`):
8+
The Dockerfile exposes two independent axes — a `GPU` build-arg
9+
(`amd` | `nvidia` | `both` | `none`, default `both`) and a `CPU` build-arg
10+
(`ON` | `OFF`, default `OFF`):
1011

1112
| Dockerfile | Output | Backends |
1213
|---|---|---|
13-
| `docker/Dockerfile.windows-cross` | `miner.exe` (PE32+) | AMD (OpenCL), NVIDIA (CUDA), or **both in one binary** |
14+
| `docker/Dockerfile.windows-cross` | `miner.exe` (PE32+) | AMD (OpenCL), NVIDIA (CUDA), both, or none — plus the CPU resolver when `CPU=ON` |
15+
16+
`CPU=ON` folds the CPU resolver into `miner.exe` and combines with any `GPU` value;
17+
`GPU=none CPU=ON` is a CPU-only `miner.exe`. The CPU resolver parallelizes via an
18+
in-process `std::thread` pool, so the clang-cl build is fully multicore (no OpenMP or
19+
libomp needed). `GPU=none CPU=OFF` is rejected (nothing to build).
1420

1521
## Helper script (PowerShell)
1622
```powershell
17-
scripts/docker-build.ps1 -Os windows-cross -Gpu both # combined AMD+NVIDIA miner.exe
23+
scripts/docker-build.ps1 -Os windows-cross -Gpu both # combined AMD+NVIDIA miner.exe
24+
scripts/docker-build.ps1 -Os windows-cross -Gpu none -Cpu # CPU-only miner.exe
1825
```
19-
Binaries are extracted to `dist/<os>-<gpu>/` (e.g. `dist/windows-cross-both/`).
26+
Binaries are extracted to `dist/<os>-<gpu>[-cpu]/` (e.g. `dist/windows-cross-both/`,
27+
`dist/windows-cross-none-cpu/`).
2028

2129
## Direct docker build
2230
```sh
2331
# Windows, combined AMD+NVIDIA -> dist/windows-cross-both/
2432
DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile.windows-cross \
2533
--build-arg GPU=both --target artifact -o dist/windows-cross-both .
34+
35+
# Windows, CPU-only -> dist/windows-cross-none-cpu/
36+
DOCKER_BUILDKIT=1 docker build -f docker/Dockerfile.windows-cross \
37+
--build-arg GPU=none --build-arg CPU=ON --target artifact -o dist/windows-cross-none-cpu .
2638
```
2739
The artifact contains `miner.exe`, the OpenCL `kernel/` directory, and the required
2840
OpenSSL + CUDA runtime DLLs. The combined `miner.exe` runs on a host that has only one

0 commit comments

Comments
 (0)