Updated readme with performance data

Added --help option
This commit is contained in:
tevador 2018-12-23 18:02:17 +01:00
parent 03913d0e81
commit 5bc26348f1
2 changed files with 107 additions and 9 deletions

View File

@ -1,12 +1,13 @@
# RandomX
RandomX is an experimental proof of work (PoW) algorithm that uses random code execution to achieve ASIC resistance.
RandomX is an experimental proof of work (PoW) algorithm that uses random code execution.
### Key features
* CPU-friendly (especially for x86 and ARM architectures)
* ASIC-resistant, FPGA-resistant, GPU-resistant
* Memory-hard (requires >4 GiB of memory)
* Web-mining resistant due to high memory requirement
* CPU-friendly (especially for x86 and ARM architectures)
* arguably ASIC-resistant
* inefficient on GPUs
* unusable for web-mining
## Virtual machine
@ -28,12 +29,83 @@ RandomX uses a simple low-level language (instruction set), which was designed s
Full description: [isa.md](doc/isa.md).
## Implementation
Proof-of-concept implementation is written in C++.
```
> bin/randomx --help
Usage: bin/randomx [OPTIONS]
Supported options:
--help shows this message
--compiled use x86-64 JIT-compiled VM (default: interpreted VM)
--lightClient use 'light-client' mode (default: full dataset mode)
--softAes use software AES (default: x86 AES-NI)
--threads T use T threads (default: 1)
--nonces N run N nonces (default: 1000)
--genAsm generate x86 asm code for nonce N
```
Two RandomX virtual machines are implemented:
### Interpreted VM
The interpreted VM is the reference implementation, which aims for maximum portability.
The VM has been tested for correctness on the following platforms:
* Linux: x86-64, ARMv7 (32-bit), ARMv8 (64-bit)
* Windows: x86, x86-64
* MacOS: x86-64
The interpreted VM supports two modes: "full dataset" mode, which requires more than 4 GiB of virtual memory, and a "light-client" mode, which requires about 64 MiB of memory, but runs significantly slower because dataset blocks are created on the fly rather than simply fetched from memory.
Software AES implementation is available for CPUs which don't support [AES-NI](https://en.wikipedia.org/wiki/AES_instruction_set).
The following table lists the performance for Intel Core i5-3230M (Ivy Bridge) CPU using a single core on Windows 64-bit, compiled with Visual Studio 2017:
|mode|required memory|AES|initialization time [s]|performance [programs/s]|
|------|----|-----|-------------------------|------------------|
|light client|64 MiB|software|1.0|9.2|
|light client|64 MiB|AES-NI|1.0|16|
|full dataset|4 GiB|software|54|40|
|full dataset|4 GiB|AES-NI|26|40|
### JIT-compiled VM
A JIT compiler is available for x86-64 CPUs. This implementation shows the approximate performance that can be achieved using optimized mining software. The JIT compiler generates generic x86-64 code without any architecture-specific optimizations. Only "full dataset" mode is supported.
For optimal performance, an x86-64 CPU needs:
* 32 KiB of L1 instruction cache per thread
* 16 KiB of L1 data cache per thread
* 240 KiB of L2 cache (exclusive) per thread
The following table lists the performance of AMD Ryzen 7 1700 (clock fixed at 3350 MHz, 1.05 Vcore, dual channel DDR4 2400 MHz) on Linux 64-bit (compiled with GCC 5.4.0).
Power consumption was measured for the whole system using a wall socket wattmeter (±1W). Table lists difference over idle power consumption. [Prime95](https://en.wikipedia.org/wiki/Prime95#Use_for_stress_testing) (small/in-place FFT) and [Cryptonight V2](https://github.com/monero-project/monero/pull/4218) power consumption are listed for comparison.
||threads|initialization time [s]|performance [programs/s]|power [W]
|-|------|----|-----|-------------------------|
|RandomX (interpreted)|1|27|52|16|
|RandomX (interpreted)|8|4.0|390|63|
|RandomX (interpreted)|16|3.5|620|74|
|RandomX (compiled)|1|27|407|17|
|RandomX (compiled)|2|14|810|26|
|RandomX (compiled)|4|7.3|1620|42|
|RandomX (compiled)|6|5.1|2410|56|
|RandomX (compiled)|8|4.0|3200|71|
|RandomX (compiled)|12|4.0|3670|82|
|RandomX (compiled)|16|3.5|4110|92|
|Cryptonight v2|8|-|-|47|
|Prime95|8|-|-|77|
|Prime95|16|-|-|81|
## Proof of work
RandomX produces a 256-bit final hash value to be used for a Hashcash-style proof evaluation.
The hash of the block header is used for the first VM initialization. The program initialization and execution are chained multiple times to prevent mining strategies that search for programs with particular properties (for example, without division).
RandomX VM can be used for PoW using the following steps:
The final result is obtained by calculating a Blake2b hash of the Register file and a checkum of the Scratchpad.
1. Initialize the VM using a 256-bit hash of any data.
2. Execute the RandomX program.
3. Calculate `blake2b(RegisterFile || t1ha2(Scratchpad))`*
\* [blake2b](https://en.wikipedia.org/wiki/BLAKE_%28hash_function%29#BLAKE2) is a cryptographic hash function, [t1ha2](https://github.com/leo-yuriev/t1ha) is a fast hashing function.
The above steps can be chained multiple times to prevent mining strategies that search for programs with particular properties (for example, without division).
## Acknowledgements
The following people have contributed to the design of RandomX:
@ -44,4 +116,11 @@ RandomX uses some source code from the following 3rd party repositories:
* Argon2d, Blake2b hashing functions: https://github.com/P-H-C/phc-winner-argon2
* PCG32 random number generator: https://github.com/imneme/pcg-c-basic
* Software AES implementation https://github.com/fireice-uk/xmr-stak
* t1ha2 hashing function: https://github.com/leo-yuriev/t1ha
* t1ha2 hashing function: https://github.com/leo-yuriev/t1ha
## Donations
XMR:
```
4B9nWtGhZfAWsTxWujPDGoWfVpJvADxkxJJTmMQp3zk98n8PdLkEKXA5g7FEUjB8JPPHdP959WDWMem3FPDTK2JUU1UbVHo
```

View File

@ -110,6 +110,18 @@ private:
std::atomic<uint64_t> hash[4];
};
void printUsage(const char* executable) {
std::cout << "Usage: " << executable << " [OPTIONS]" << std::endl;
std::cout << "Supported options:" << std::endl;
std::cout << "\t--help\t\t\tshows this message" << std::endl;
std::cout << "\t--compiled\t\tuse x86-64 JIT-compiled VM (default: interpreted VM)" << std::endl;
std::cout << "\t--lightClient\t\tuse 'light-client' mode (default: full dataset mode)" << std::endl;
std::cout << "\t--softAes\t\tuse software AES (default: x86 AES-NI)" << std::endl;
std::cout << "\t--threads T\t\tuse T threads (default: 1)" << std::endl;
std::cout << "\t--nonces N\t\trun N nonces (default: 1000)" << std::endl;
std::cout << "\t--genAsm\t\tgenerate x86 asm code for nonce N" << std::endl;
}
void generateAsm(int nonce) {
uint64_t hash[4];
unsigned char blockTemplate[] = {
@ -158,8 +170,15 @@ void mine(RandomX::VirtualMachine* vm, std::atomic<int>& atomicNonce, AtomicHash
}
int main(int argc, char** argv) {
bool softAes, lightClient, genAsm, compiled;
bool softAes, lightClient, genAsm, compiled, help;
int programCount, threadCount;
readOption("--help", argc, argv, help);
if (help) {
printUsage(argv[0]);
return 0;
}
readOption("--softAes", argc, argv, softAes);
readOption("--lightClient", argc, argv, lightClient);
readOption("--genAsm", argc, argv, genAsm);