Allow more than one worker thread per GPU device #4
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #1. The cheapest change on the list: hides the per-batch readback bubble on the origin wgpu engine with no kernel work.
Problem
run_single_batchincrates/engine-gpu/src/lib.rsis synchronous: write buffers, submit, block on the fence, map, read, unmap, then the worker computes the next midstate and submits again. One worker per card means the card is idle for the whole turnaround. At the default 1M batch a 5090 finishes the kernel in about 2.7 ms, so a few hundred microseconds of turnaround is a double-digit loss.Why it is cheap
The engine already supports it by accident. Worker threads get a device by
device_counter % contexts.len()(thread-localASSIGNED_GPU_DEVICE), and each thread owns its ownGpuResources(thread-localWORKER_RESOURCES, its own buffers and bind group). Two threads on onewgpu::DeviceandQueueare legal; wgpu serialises at the queue and the GPU executes the two submissions back to back. So while thread A is in readback, thread B's dispatch is already queued and the card stays busy.The only thing preventing it is the count check in
resolve_gpu_configuration(crates/miner-service/src/lib.rs, "Requested N GPU devices but only M available").Change
--gpu-workers-per-device <N>, default 1 (origin behaviour). Total GPU workers = devices x N.resolve_gpu_configurationvalidatesrequested_devices <= availableas today, then multiplies.WorkerPool::newis unchanged; it just gets a biggergpu_devicescount.miner_gpu_devicesmetric keeps reporting devices, not workers, so the fleet dashboard reads the same.About 20 lines, all in the two files #1 already allows a standing diff in.
Measure
Harness runs at N = 1, 2, 3 on one 5090 at the 1M default and at 16M. Expect N = 2 to recover most of the bubble at 1M and matter less at 16M. If N = 3 is not better than N = 2, cap the flag at 2 in the docs.
Interaction with other workstreams
Superseded on the wgpu engine by proper double-buffering, and irrelevant to
engine-cudawhich pipelines internally. Worth doing first anyway: it ships in an afternoon, and its number is the baseline the double-buffering issue has to beat.Origin coupling
None beyond the flag. If origin later adds its own pipelining, the flag becomes a no-op and can be dropped in that merge.
Closing as superseded by measurement. The bubble this flag would hide is 1.9% of a batch on the 4090 (
miner_gpu_batch_seconds, #9) and the CUDA engine's batches are shorter still. The harness already supports oversubscribing a card (--workersabove the card count, #11) for anyone who wants to measure it; a miner flag for under 2% is not worth the surface. If pipelining is ever revisited it is #5.