diff options
| author | Bitflash <btf01@proton.me> | 2026-07-30 14:07:50 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-07-30 14:07:50 -0300 |
| commit | 225d0210f881acb10a3dfaf9bc5a23446bc12d21 (patch) | |
| tree | f8f15df707084a64924bed42e526c2e0ef43b1b9 /src/net.h | |
| parent | 9f7141b28e2da9db7d7cb099d1f13f28742ff0fa (diff) | |
mine: hash on every core instead of one (#52)
Satoshi left a note above ThreadBitcoinMiner in 2009:
//// todo: start one thread per processor,
//// use getenv("NUMBER_OF_PROCESSORS")
Nobody did, and it stopped being a nicety when the proof of work
became RandomX. SHA-256d on a 2009 desktop lost little to a
single thread. RandomX is built to be fed by every core at once,
so one thread on a 32-core machine mines at a thirty-second of
what the box can do -- and the only outward sign is a CPU that
looks suspiciously idle. A user reported exactly that: 30 minutes
of "Mining", no blocks, Bitflash sitting at 3.3% CPU while the
2 GB dataset was allocated and fast mode was active. Nothing was
broken. It was hashing on one core.
bitflash -gen # every core but one
bitflash -gen -genproclimit=8 # exactly eight
Automatic leaves one core to the rest of the node -- accepting
blocks, talking to peers, drawing the window -- because a node
that mines beautifully while falling behind the chain has won
nothing. /genproclimit overrides it, and a count several times
the core count is refused rather than quietly thrashing.
The wrapper was already built for this: RandomXCreateMinerVM says
"own VM, not shared", and the ~2 GB dataset is one allocation
every thread reads. Only the 2 MB scratchpad multiplies, so
sixteen threads cost about 32 MB more than one. The startup line
says so, because "why is it using 2 GB" is the first question
anyone asks.
Two things had to be right for this to be safe:
- Shutdown. Miners share slot 3 of vfThreadRunning and StopNode
waits for every slot before DBFlush tears the database down.
With several, the first one out announced that everyone had
finished while the rest were still calling ProcessBlock, so
they are counted now and only the last one clears the flag.
The three CheckForShutdown(3) calls inside the miner became
plain returns: _endthread() does not unwind on Windows, so
the bookkeeping would have been skipped there.
- Duplicated work. Each thread makes its own key, and the
coinbase pays it, so every thread has a different merkle root
and searches a different space. Block assembly was already
under cs_main and cs_mapTransactions; AddKey and ProcessBlock
take their own locks.
Verified on both platforms: four distinct thread ids reach the
hashing loop and all report back on shutdown, which exits 0 with
DBFlush running. Auto picks cores-1 (1 on a 2-core box, correctly
reported). Speedup itself needs a many-core machine to show and
has not been measured here -- the claim in this message is about
threads doing work, not a benchmark.
Not touched: RandomX's memory. RANDOMX_DATASET_BASE_SIZE and
SCRATCHPAD_L3 are part of the hash function, so a knob for "use
more RAM" would either do nothing or fork the chain. Threads are
the only real dial.
Diffstat (limited to 'src/net.h')
| -rw-r--r-- | src/net.h | 2 |
1 files changed, 2 insertions, 0 deletions
| @@ -58,6 +58,8 @@ int BtfPexAccept(const std::vector<std::string>& vDesc); | |||
| 58 | void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1); | 58 | void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1); |
| 59 | bool AnySubscribed(unsigned int nChannel); | 59 | bool AnySubscribed(unsigned int nChannel); |
| 60 | void ThreadBitcoinMiner(void* parg); | 60 | void ThreadBitcoinMiner(void* parg); |
| 61 | // Starts MinerThreadCount() miners; returns how many came up. | ||
| 62 | int StartMinerThreads(); | ||
| 61 | bool StartNode(string& strError=REF(string())); | 63 | bool StartNode(string& strError=REF(string())); |
| 62 | bool StopNode(); | 64 | bool StopNode(); |
| 63 | void CheckForShutdown(int n); | 65 | void CheckForShutdown(int n); |