mirror of
https://git.wownero.com/wownero/RandomWOW.git
synced 2024-12-22 15:58:53 +00:00
Implemented Dataset size increase per epoch
This commit is contained in:
parent
e65d9da66c
commit
2edf05cedc
@ -25,8 +25,9 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
|||||||
namespace RandomX {
|
namespace RandomX {
|
||||||
|
|
||||||
static_assert(RANDOMX_ARGON_MEMORY % (RANDOMX_ARGON_LANES * ARGON2_SYNC_POINTS) == 0, "RANDOMX_ARGON_MEMORY - invalid value");
|
static_assert(RANDOMX_ARGON_MEMORY % (RANDOMX_ARGON_LANES * ARGON2_SYNC_POINTS) == 0, "RANDOMX_ARGON_MEMORY - invalid value");
|
||||||
|
static_assert(RANDOMX_ARGON_GROWTH % (RANDOMX_ARGON_LANES * ARGON2_SYNC_POINTS) == 0, "RANDOMX_ARGON_GROWTH - invalid value");
|
||||||
|
|
||||||
void Cache::argonFill(const void* seed, size_t seedSize) {
|
void argonFill(Cache& cache, const void* seed, size_t seedSize) {
|
||||||
uint32_t memory_blocks, segment_length;
|
uint32_t memory_blocks, segment_length;
|
||||||
argon2_instance_t instance;
|
argon2_instance_t instance;
|
||||||
argon2_context context;
|
argon2_context context;
|
||||||
@ -42,7 +43,7 @@ namespace RandomX {
|
|||||||
context.ad = NULL;
|
context.ad = NULL;
|
||||||
context.adlen = 0;
|
context.adlen = 0;
|
||||||
context.t_cost = RANDOMX_ARGON_ITERATIONS;
|
context.t_cost = RANDOMX_ARGON_ITERATIONS;
|
||||||
context.m_cost = RANDOMX_ARGON_MEMORY;
|
context.m_cost = cache.size / ArgonBlockSize;
|
||||||
context.lanes = RANDOMX_ARGON_LANES;
|
context.lanes = RANDOMX_ARGON_LANES;
|
||||||
context.threads = 1;
|
context.threads = 1;
|
||||||
context.allocate_cbk = NULL;
|
context.allocate_cbk = NULL;
|
||||||
@ -65,7 +66,7 @@ namespace RandomX {
|
|||||||
instance.lanes = context.lanes;
|
instance.lanes = context.lanes;
|
||||||
instance.threads = context.threads;
|
instance.threads = context.threads;
|
||||||
instance.type = Argon2_d;
|
instance.type = Argon2_d;
|
||||||
instance.memory = (block*)memory;
|
instance.memory = (block*)cache.memory;
|
||||||
|
|
||||||
if (instance.threads > instance.lanes) {
|
if (instance.threads > instance.lanes) {
|
||||||
instance.threads = instance.lanes;
|
instance.threads = instance.lanes;
|
||||||
@ -78,9 +79,4 @@ namespace RandomX {
|
|||||||
|
|
||||||
fill_memory_blocks(&instance);
|
fill_memory_blocks(&instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cache::initialize(const void* seed, size_t seedSize) {
|
|
||||||
//Argon2d memory fill
|
|
||||||
argonFill(seed, seedSize);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -22,50 +22,31 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
#include "dataset.hpp"
|
#include "intrinPortable.h"
|
||||||
#include "virtualMemory.hpp"
|
#include "virtualMemory.hpp"
|
||||||
|
|
||||||
namespace RandomX {
|
namespace RandomX {
|
||||||
|
|
||||||
class Cache {
|
void argonFill(Cache& cache, const void* seed, size_t seedSize);
|
||||||
public:
|
|
||||||
static void* alloc(bool largePages) {
|
inline uint8_t* allocCache(size_t size, bool largePages) {
|
||||||
if (largePages) {
|
if (largePages) {
|
||||||
return allocLargePagesMemory(sizeof(Cache));
|
return (uint8_t*)allocLargePagesMemory(size);
|
||||||
}
|
|
||||||
else {
|
|
||||||
void* ptr = _mm_malloc(sizeof(Cache), sizeof(__m128i));
|
|
||||||
if (ptr == nullptr)
|
|
||||||
throw std::bad_alloc();
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static void dealloc(Cache* cache, bool largePages) {
|
else {
|
||||||
if (largePages) {
|
|
||||||
freePagedMemory(cache, sizeof(Cache));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_mm_free(cache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*void* operator new(size_t size) {
|
|
||||||
void* ptr = _mm_malloc(size, sizeof(__m128i));
|
void* ptr = _mm_malloc(size, sizeof(__m128i));
|
||||||
if (ptr == nullptr)
|
if (ptr == nullptr)
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
return ptr;
|
return (uint8_t*)ptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void operator delete(void* ptr) {
|
inline void deallocCache(Cache cache, bool largePages) {
|
||||||
_mm_free(ptr);
|
if (largePages) {
|
||||||
}*/
|
freePagedMemory(cache.memory, cache.size);
|
||||||
|
|
||||||
void initialize(const void* seed, size_t seedSize);
|
|
||||||
|
|
||||||
const uint8_t* getCache() const {
|
|
||||||
return memory;
|
|
||||||
}
|
}
|
||||||
private:
|
else {
|
||||||
uint8_t memory[CacheSize];
|
_mm_free(cache.memory);
|
||||||
void argonFill(const void* seed, size_t seedSize);
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
@ -23,25 +23,26 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
namespace RandomX {
|
namespace RandomX {
|
||||||
|
|
||||||
static_assert(sizeof(MemoryRegisters) == 2 * sizeof(addr_t) + sizeof(uintptr_t), "Invalid alignment of struct RandomX::MemoryRegisters");
|
//static_assert(sizeof(MemoryRegisters) == 2 * sizeof(addr_t) + sizeof(uintptr_t), "Invalid alignment of struct RandomX::MemoryRegisters");
|
||||||
static_assert(sizeof(RegisterFile) == 256, "Invalid alignment of struct RandomX::RegisterFile");
|
static_assert(sizeof(RegisterFile) == 256, "Invalid alignment of struct RandomX::RegisterFile");
|
||||||
|
|
||||||
CompiledVirtualMachine::CompiledVirtualMachine() {
|
CompiledVirtualMachine::CompiledVirtualMachine() {
|
||||||
totalSize = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompiledVirtualMachine::setDataset(dataset_t ds) {
|
void CompiledVirtualMachine::setDataset(dataset_t ds, uint64_t size) {
|
||||||
mem.ds = ds;
|
mem.ds = ds;
|
||||||
|
datasetRange = (size - RANDOMX_DATASET_SIZE + CacheLineSize) / CacheLineSize;
|
||||||
|
datasetBasePtr = ds.dataset.memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompiledVirtualMachine::initialize() {
|
void CompiledVirtualMachine::initialize() {
|
||||||
VirtualMachine::initialize();
|
VirtualMachine::initialize();
|
||||||
compiler.generateProgram(program);
|
compiler.generateProgram(program);
|
||||||
|
mem.ds.dataset.memory = datasetBasePtr + (datasetBase * CacheLineSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompiledVirtualMachine::execute() {
|
void CompiledVirtualMachine::execute() {
|
||||||
//executeProgram(reg, mem, scratchpad, InstructionCount);
|
//executeProgram(reg, mem, scratchpad, InstructionCount);
|
||||||
//totalSize += compiler.getCodeSize();
|
|
||||||
compiler.getProgramFunc()(reg, mem, scratchpad, RANDOMX_PROGRAM_ITERATIONS);
|
compiler.getProgramFunc()(reg, mem, scratchpad, RANDOMX_PROGRAM_ITERATIONS);
|
||||||
#ifdef TRACEVM
|
#ifdef TRACEVM
|
||||||
for (int32_t i = InstructionCount - 1; i >= 0; --i) {
|
for (int32_t i = InstructionCount - 1; i >= 0; --i) {
|
||||||
|
@ -42,20 +42,17 @@ namespace RandomX {
|
|||||||
_mm_free(ptr);
|
_mm_free(ptr);
|
||||||
}
|
}
|
||||||
CompiledVirtualMachine();
|
CompiledVirtualMachine();
|
||||||
void setDataset(dataset_t ds) override;
|
void setDataset(dataset_t ds, uint64_t size) override;
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
virtual void execute() override;
|
virtual void execute() override;
|
||||||
void* getProgram() {
|
void* getProgram() {
|
||||||
return compiler.getCode();
|
return compiler.getCode();
|
||||||
}
|
}
|
||||||
uint64_t getTotalSize() {
|
|
||||||
return totalSize;
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
#ifdef TRACEVM
|
#ifdef TRACEVM
|
||||||
convertible_t tracepad[InstructionCount];
|
convertible_t tracepad[InstructionCount];
|
||||||
#endif
|
#endif
|
||||||
JitCompilerX86 compiler;
|
JitCompilerX86 compiler;
|
||||||
uint64_t totalSize;
|
uint8_t* datasetBasePtr;
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -50,13 +50,13 @@ namespace RandomX {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterpretedVirtualMachine::setDataset(dataset_t ds) {
|
void InterpretedVirtualMachine::setDataset(dataset_t ds, uint64_t size) {
|
||||||
if (asyncWorker) {
|
if (asyncWorker) {
|
||||||
if (softAes) {
|
if (softAes) {
|
||||||
mem.ds.asyncWorker = new LightClientAsyncWorker<true>(ds.cache);
|
mem.ds.asyncWorker = new LightClientAsyncWorker(ds.cache);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mem.ds.asyncWorker = new LightClientAsyncWorker<false>(ds.cache);
|
mem.ds.asyncWorker = new LightClientAsyncWorker(ds.cache);
|
||||||
}
|
}
|
||||||
readDataset = &datasetReadLightAsync;
|
readDataset = &datasetReadLightAsync;
|
||||||
}
|
}
|
||||||
@ -64,6 +64,7 @@ namespace RandomX {
|
|||||||
mem.ds = ds;
|
mem.ds = ds;
|
||||||
readDataset = &datasetReadLight;
|
readDataset = &datasetReadLight;
|
||||||
}
|
}
|
||||||
|
datasetRange = (size - RANDOMX_DATASET_SIZE + CacheLineSize) / CacheLineSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterpretedVirtualMachine::initialize() {
|
void InterpretedVirtualMachine::initialize() {
|
||||||
@ -337,20 +338,20 @@ namespace RandomX {
|
|||||||
|
|
||||||
if (asyncWorker) {
|
if (asyncWorker) {
|
||||||
ILightClientAsyncWorker* aw = mem.ds.asyncWorker;
|
ILightClientAsyncWorker* aw = mem.ds.asyncWorker;
|
||||||
const uint64_t* datasetLine = aw->getBlock(mem.ma);
|
const uint64_t* datasetLine = aw->getBlock(datasetBase + mem.ma);
|
||||||
for (int i = 0; i < RegistersCount; ++i)
|
for (int i = 0; i < RegistersCount; ++i)
|
||||||
r[i] ^= datasetLine[i];
|
r[i] ^= datasetLine[i];
|
||||||
mem.mx ^= r[readReg2] ^ r[readReg3];
|
mem.mx ^= r[readReg2] ^ r[readReg3];
|
||||||
mem.mx &= CacheLineAlignMask; //align to cache line
|
mem.mx &= CacheLineAlignMask; //align to cache line
|
||||||
std::swap(mem.mx, mem.ma);
|
std::swap(mem.mx, mem.ma);
|
||||||
aw->prepareBlock(mem.ma);
|
aw->prepareBlock(datasetBase + mem.ma);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mem.mx ^= r[readReg2] ^ r[readReg3];
|
mem.mx ^= r[readReg2] ^ r[readReg3];
|
||||||
mem.mx &= CacheLineAlignMask;
|
//mem.mx &= CacheLineAlignMask;
|
||||||
Cache* cache = mem.ds.cache;
|
Cache& cache = mem.ds.cache;
|
||||||
uint64_t datasetLine[CacheLineSize / sizeof(uint64_t)];
|
uint64_t datasetLine[CacheLineSize / sizeof(uint64_t)];
|
||||||
initBlock(cache->getCache(), (uint8_t*)datasetLine, mem.ma / CacheLineSize);
|
initBlock(cache, (uint8_t*)datasetLine, datasetBase + mem.ma / CacheLineSize);
|
||||||
for (int i = 0; i < RegistersCount; ++i)
|
for (int i = 0; i < RegistersCount; ++i)
|
||||||
r[i] ^= datasetLine[i];
|
r[i] ^= datasetLine[i];
|
||||||
std::swap(mem.mx, mem.ma);
|
std::swap(mem.mx, mem.ma);
|
||||||
|
@ -72,7 +72,7 @@ namespace RandomX {
|
|||||||
}
|
}
|
||||||
InterpretedVirtualMachine(bool soft, bool async) : softAes(soft), asyncWorker(async) {}
|
InterpretedVirtualMachine(bool soft, bool async) : softAes(soft), asyncWorker(async) {}
|
||||||
~InterpretedVirtualMachine();
|
~InterpretedVirtualMachine();
|
||||||
void setDataset(dataset_t ds) override;
|
void setDataset(dataset_t ds, uint64_t size) override;
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
void execute() override;
|
void execute() override;
|
||||||
private:
|
private:
|
||||||
|
@ -23,8 +23,7 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
namespace RandomX {
|
namespace RandomX {
|
||||||
|
|
||||||
template<bool softAes>
|
LightClientAsyncWorker::LightClientAsyncWorker(const Cache& c) : ILightClientAsyncWorker(c), output(nullptr), hasWork(false),
|
||||||
LightClientAsyncWorker<softAes>::LightClientAsyncWorker(const Cache* c) : ILightClientAsyncWorker(c), output(nullptr), hasWork(false),
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
sw(true),
|
sw(true),
|
||||||
#endif
|
#endif
|
||||||
@ -32,8 +31,7 @@ namespace RandomX {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool softAes>
|
void LightClientAsyncWorker::prepareBlock(addr_t addr) {
|
||||||
void LightClientAsyncWorker<softAes>::prepareBlock(addr_t addr) {
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
std::cout << sw.getElapsed() << ": prepareBlock-enter " << addr / CacheLineSize << std::endl;
|
std::cout << sw.getElapsed() << ": prepareBlock-enter " << addr / CacheLineSize << std::endl;
|
||||||
#endif
|
#endif
|
||||||
@ -50,14 +48,13 @@ namespace RandomX {
|
|||||||
notifier.notify_one();
|
notifier.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool softAes>
|
const uint64_t* LightClientAsyncWorker::getBlock(addr_t addr) {
|
||||||
const uint64_t* LightClientAsyncWorker<softAes>::getBlock(addr_t addr) {
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
std::cout << sw.getElapsed() << ": getBlock-enter " << addr / CacheLineSize << std::endl;
|
std::cout << sw.getElapsed() << ": getBlock-enter " << addr / CacheLineSize << std::endl;
|
||||||
#endif
|
#endif
|
||||||
uint32_t currentBlock = addr / CacheLineSize;
|
uint32_t currentBlock = addr / CacheLineSize;
|
||||||
if (currentBlock != startBlock || output != currentLine.data()) {
|
if (currentBlock != startBlock || output != currentLine.data()) {
|
||||||
initBlock(cache->getCache(), (uint8_t*)currentLine.data(), currentBlock);
|
initBlock(cache, (uint8_t*)currentLine.data(), currentBlock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sync();
|
sync();
|
||||||
@ -68,8 +65,7 @@ namespace RandomX {
|
|||||||
return currentLine.data();
|
return currentLine.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool softAes>
|
void LightClientAsyncWorker::prepareBlocks(void* out, uint32_t startBlock, uint32_t blockCount) {
|
||||||
void LightClientAsyncWorker<softAes>::prepareBlocks(void* out, uint32_t startBlock, uint32_t blockCount) {
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
std::cout << sw.getElapsed() << ": prepareBlocks-enter " << startBlock << "/" << blockCount << std::endl;
|
std::cout << sw.getElapsed() << ": prepareBlocks-enter " << startBlock << "/" << blockCount << std::endl;
|
||||||
#endif
|
#endif
|
||||||
@ -83,21 +79,18 @@ namespace RandomX {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool softAes>
|
void LightClientAsyncWorker::getBlocks(void* out, uint32_t startBlock, uint32_t blockCount) {
|
||||||
void LightClientAsyncWorker<softAes>::getBlocks(void* out, uint32_t startBlock, uint32_t blockCount) {
|
|
||||||
for (uint32_t i = 0; i < blockCount; ++i) {
|
for (uint32_t i = 0; i < blockCount; ++i) {
|
||||||
initBlock(cache->getCache(), (uint8_t*)out + CacheLineSize * i, startBlock + i);
|
initBlock(cache, (uint8_t*)out + CacheLineSize * i, startBlock + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool softAes>
|
void LightClientAsyncWorker::sync() {
|
||||||
void LightClientAsyncWorker<softAes>::sync() {
|
|
||||||
std::unique_lock<std::mutex> lk(mutex);
|
std::unique_lock<std::mutex> lk(mutex);
|
||||||
notifier.wait(lk, [this] { return !hasWork; });
|
notifier.wait(lk, [this] { return !hasWork; });
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool softAes>
|
void LightClientAsyncWorker::runWorker() {
|
||||||
void LightClientAsyncWorker<softAes>::runWorker() {
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
std::cout << sw.getElapsed() << ": runWorker-enter " << std::endl;
|
std::cout << sw.getElapsed() << ": runWorker-enter " << std::endl;
|
||||||
#endif
|
#endif
|
||||||
@ -108,7 +101,7 @@ namespace RandomX {
|
|||||||
std::cout << sw.getElapsed() << ": runWorker-getBlocks " << startBlock << "/" << blockCount << std::endl;
|
std::cout << sw.getElapsed() << ": runWorker-getBlocks " << startBlock << "/" << blockCount << std::endl;
|
||||||
#endif
|
#endif
|
||||||
//getBlocks(output, startBlock, blockCount);
|
//getBlocks(output, startBlock, blockCount);
|
||||||
initBlock(cache->getCache(), (uint8_t*)output, startBlock);
|
initBlock(cache, (uint8_t*)output, startBlock);
|
||||||
hasWork = false;
|
hasWork = false;
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
std::cout << sw.getElapsed() << ": runWorker-finished " << startBlock << "/" << blockCount << std::endl;
|
std::cout << sw.getElapsed() << ": runWorker-finished " << startBlock << "/" << blockCount << std::endl;
|
||||||
@ -117,7 +110,4 @@ namespace RandomX {
|
|||||||
notifier.notify_one();
|
notifier.notify_one();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template class LightClientAsyncWorker<true>;
|
|
||||||
template class LightClientAsyncWorker<false>;
|
|
||||||
}
|
}
|
@ -31,14 +31,11 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
namespace RandomX {
|
namespace RandomX {
|
||||||
|
|
||||||
class Cache;
|
|
||||||
|
|
||||||
using DatasetLine = std::array<uint64_t, CacheLineSize / sizeof(uint64_t)>;
|
using DatasetLine = std::array<uint64_t, CacheLineSize / sizeof(uint64_t)>;
|
||||||
|
|
||||||
template<bool softAes>
|
|
||||||
class LightClientAsyncWorker : public ILightClientAsyncWorker {
|
class LightClientAsyncWorker : public ILightClientAsyncWorker {
|
||||||
public:
|
public:
|
||||||
LightClientAsyncWorker(const Cache*);
|
LightClientAsyncWorker(const Cache&);
|
||||||
void prepareBlock(addr_t) final;
|
void prepareBlock(addr_t) final;
|
||||||
void prepareBlocks(void* out, uint32_t startBlock, uint32_t blockCount) final;
|
void prepareBlocks(void* out, uint32_t startBlock, uint32_t blockCount) final;
|
||||||
const uint64_t* getBlock(addr_t) final;
|
const uint64_t* getBlock(addr_t) final;
|
||||||
|
@ -58,7 +58,7 @@ namespace RandomX {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VirtualMachine::VirtualMachine() {
|
VirtualMachine::VirtualMachine() {
|
||||||
mem.ds.dataset = nullptr;
|
mem.ds.dataset.memory = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualMachine::resetRoundingMode() {
|
void VirtualMachine::resetRoundingMode() {
|
||||||
@ -84,6 +84,7 @@ namespace RandomX {
|
|||||||
readReg2 = 4 + (addressRegisters & 1);
|
readReg2 = 4 + (addressRegisters & 1);
|
||||||
addressRegisters >>= 1;
|
addressRegisters >>= 1;
|
||||||
readReg3 = 6 + (addressRegisters & 1);
|
readReg3 = 6 + (addressRegisters & 1);
|
||||||
|
datasetBase = program.getEntropy(14) % datasetRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool softAes>
|
template<bool softAes>
|
||||||
|
@ -30,7 +30,7 @@ namespace RandomX {
|
|||||||
public:
|
public:
|
||||||
VirtualMachine();
|
VirtualMachine();
|
||||||
virtual ~VirtualMachine() {}
|
virtual ~VirtualMachine() {}
|
||||||
virtual void setDataset(dataset_t ds) = 0;
|
virtual void setDataset(dataset_t ds, uint64_t size) = 0;
|
||||||
void setScratchpad(void* ptr) {
|
void setScratchpad(void* ptr) {
|
||||||
scratchpad = (uint8_t*)ptr;
|
scratchpad = (uint8_t*)ptr;
|
||||||
}
|
}
|
||||||
@ -51,5 +51,7 @@ namespace RandomX {
|
|||||||
MemoryRegisters mem;
|
MemoryRegisters mem;
|
||||||
uint8_t* scratchpad;
|
uint8_t* scratchpad;
|
||||||
uint32_t readReg0, readReg1, readReg2, readReg3;
|
uint32_t readReg0, readReg1, readReg2, readReg3;
|
||||||
|
uint32_t datasetRange;
|
||||||
|
uint32_t datasetBase;
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -29,7 +29,8 @@ namespace RandomX {
|
|||||||
static_assert((RANDOMX_ARGON_MEMORY & (RANDOMX_ARGON_MEMORY - 1)) == 0, "RANDOMX_ARGON_MEMORY must be a power of 2.");
|
static_assert((RANDOMX_ARGON_MEMORY & (RANDOMX_ARGON_MEMORY - 1)) == 0, "RANDOMX_ARGON_MEMORY must be a power of 2.");
|
||||||
static_assert((RANDOMX_DATASET_SIZE & (RANDOMX_DATASET_SIZE - 1)) == 0, "RANDOMX_DATASET_SIZE must be a power of 2.");
|
static_assert((RANDOMX_DATASET_SIZE & (RANDOMX_DATASET_SIZE - 1)) == 0, "RANDOMX_DATASET_SIZE must be a power of 2.");
|
||||||
static_assert(RANDOMX_DATASET_SIZE <= 4294967296ULL, "RANDOMX_DATASET_SIZE must not exceed 4294967296.");
|
static_assert(RANDOMX_DATASET_SIZE <= 4294967296ULL, "RANDOMX_DATASET_SIZE must not exceed 4294967296.");
|
||||||
static_assert(RANDOMX_DS_GROWTH_RATE % 64 == 0, "RANDOMX_DS_GROWTH_RATE must be divisible by 64.");
|
static_assert(RANDOMX_DS_GROWTH % 64 == 0, "RANDOMX_DS_GROWTH must be divisible by 64.");
|
||||||
|
static_assert(RANDOMX_ARGON_GROWTH >= 0, "RANDOMX_ARGON_GROWTH must be greater than or equal to 0.");
|
||||||
static_assert(RANDOMX_PROGRAM_SIZE > 0, "RANDOMX_PROGRAM_SIZE must be greater than 0");
|
static_assert(RANDOMX_PROGRAM_SIZE > 0, "RANDOMX_PROGRAM_SIZE must be greater than 0");
|
||||||
static_assert(RANDOMX_PROGRAM_ITERATIONS > 0, "RANDOMX_PROGRAM_ITERATIONS must be greater than 0");
|
static_assert(RANDOMX_PROGRAM_ITERATIONS > 0, "RANDOMX_PROGRAM_ITERATIONS must be greater than 0");
|
||||||
static_assert(RANDOMX_PROGRAM_COUNT > 0, "RANDOMX_PROGRAM_COUNT must be greater than 0");
|
static_assert(RANDOMX_PROGRAM_COUNT > 0, "RANDOMX_PROGRAM_COUNT must be greater than 0");
|
||||||
@ -54,6 +55,7 @@ namespace RandomX {
|
|||||||
|
|
||||||
constexpr int SeedSize = 32;
|
constexpr int SeedSize = 32;
|
||||||
constexpr int ResultSize = 64;
|
constexpr int ResultSize = 64;
|
||||||
|
constexpr int ArgonBlockSize = 1024;
|
||||||
constexpr int ArgonSaltSize = sizeof(RANDOMX_ARGON_SALT) - 1;
|
constexpr int ArgonSaltSize = sizeof(RANDOMX_ARGON_SALT) - 1;
|
||||||
constexpr int CacheLineSize = 64;
|
constexpr int CacheLineSize = 64;
|
||||||
constexpr uint32_t CacheLineAlignMask = (RANDOMX_DATASET_SIZE - 1) & ~(CacheLineSize - 1);
|
constexpr uint32_t CacheLineAlignMask = (RANDOMX_DATASET_SIZE - 1) & ~(CacheLineSize - 1);
|
||||||
@ -94,7 +96,13 @@ namespace RandomX {
|
|||||||
constexpr int ScratchpadL3Mask64 = (ScratchpadL3 / 8 - 1) * 64;
|
constexpr int ScratchpadL3Mask64 = (ScratchpadL3 / 8 - 1) * 64;
|
||||||
constexpr int RegistersCount = 8;
|
constexpr int RegistersCount = 8;
|
||||||
|
|
||||||
class Cache;
|
struct Cache {
|
||||||
|
uint8_t* memory;
|
||||||
|
uint64_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Dataset : public Cache {
|
||||||
|
};
|
||||||
|
|
||||||
class ILightClientAsyncWorker {
|
class ILightClientAsyncWorker {
|
||||||
public:
|
public:
|
||||||
@ -104,17 +112,17 @@ namespace RandomX {
|
|||||||
virtual const uint64_t* getBlock(addr_t) = 0;
|
virtual const uint64_t* getBlock(addr_t) = 0;
|
||||||
virtual void getBlocks(void* out, uint32_t startBlock, uint32_t blockCount) = 0;
|
virtual void getBlocks(void* out, uint32_t startBlock, uint32_t blockCount) = 0;
|
||||||
virtual void sync() = 0;
|
virtual void sync() = 0;
|
||||||
const Cache* getCache() {
|
const Cache& getCache() {
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
ILightClientAsyncWorker(const Cache* c) : cache(c) {}
|
ILightClientAsyncWorker(const Cache& c) : cache(c) {}
|
||||||
const Cache* cache;
|
const Cache& cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
union dataset_t {
|
union dataset_t {
|
||||||
uint8_t* dataset;
|
Dataset dataset;
|
||||||
Cache* cache;
|
Cache cache;
|
||||||
ILightClientAsyncWorker* asyncWorker;
|
ILightClientAsyncWorker* asyncWorker;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,6 +22,9 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
|||||||
//Cache size in KiB. Must be a power of 2.
|
//Cache size in KiB. Must be a power of 2.
|
||||||
#define RANDOMX_ARGON_MEMORY (256 * 1024)
|
#define RANDOMX_ARGON_MEMORY (256 * 1024)
|
||||||
|
|
||||||
|
//Cache growth per epoch in KiB.
|
||||||
|
#define RANDOMX_ARGON_GROWTH 0
|
||||||
|
|
||||||
//Number of Argon2d iterations for Cache initialization
|
//Number of Argon2d iterations for Cache initialization
|
||||||
#define RANDOMX_ARGON_ITERATIONS 3
|
#define RANDOMX_ARGON_ITERATIONS 3
|
||||||
|
|
||||||
@ -38,7 +41,10 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
|||||||
#define RANDOMX_DATASET_SIZE (4ULL * 1024 * 1024 * 1024)
|
#define RANDOMX_DATASET_SIZE (4ULL * 1024 * 1024 * 1024)
|
||||||
|
|
||||||
//Dataset growth per epoch in bytes. Must be divisible by 64.
|
//Dataset growth per epoch in bytes. Must be divisible by 64.
|
||||||
#define RANDOMX_DS_GROWTH_RATE (2 * 1024 * 1024)
|
#define RANDOMX_DS_GROWTH (2 * 1024 * 1024)
|
||||||
|
|
||||||
|
//Number of blocks per epoch
|
||||||
|
#define RANDOMX_EPOCH_BLOCKS 1024
|
||||||
|
|
||||||
//Number of instructions in a RandomX program
|
//Number of instructions in a RandomX program
|
||||||
#define RANDOMX_PROGRAM_SIZE 256
|
#define RANDOMX_PROGRAM_SIZE 256
|
||||||
@ -47,7 +53,7 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
|||||||
#define RANDOMX_PROGRAM_ITERATIONS 2048
|
#define RANDOMX_PROGRAM_ITERATIONS 2048
|
||||||
|
|
||||||
//Number of chained VM executions per hash
|
//Number of chained VM executions per hash
|
||||||
#define RANDOMX_PROGRAM_COUNT 8
|
#define RANDOMX_PROGRAM_COUNT 8
|
||||||
|
|
||||||
//Scratchpad L3 size in bytes. Must be a power of 2.
|
//Scratchpad L3 size in bytes. Must be a power of 2.
|
||||||
#define RANDOMX_SCRATCHPAD_L3 (2 * 1024 * 1024)
|
#define RANDOMX_SCRATCHPAD_L3 (2 * 1024 * 1024)
|
||||||
@ -63,39 +69,42 @@ Instruction frequencies (per 256 opcodes)
|
|||||||
Total sum of frequencies must be 256
|
Total sum of frequencies must be 256
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define RANDOMX_FREQ_IADD_R 12
|
#define RANDOMX_FREQ_IADD_R 12
|
||||||
#define RANDOMX_FREQ_IADD_M 7
|
#define RANDOMX_FREQ_IADD_M 7
|
||||||
#define RANDOMX_FREQ_IADD_RC 16
|
#define RANDOMX_FREQ_IADD_RC 16
|
||||||
#define RANDOMX_FREQ_ISUB_R 12
|
#define RANDOMX_FREQ_ISUB_R 12
|
||||||
#define RANDOMX_FREQ_ISUB_M 7
|
#define RANDOMX_FREQ_ISUB_M 7
|
||||||
#define RANDOMX_FREQ_IMUL_9C 9
|
#define RANDOMX_FREQ_IMUL_9C 9
|
||||||
#define RANDOMX_FREQ_IMUL_R 16
|
#define RANDOMX_FREQ_IMUL_R 16
|
||||||
#define RANDOMX_FREQ_IMUL_M 4
|
#define RANDOMX_FREQ_IMUL_M 4
|
||||||
#define RANDOMX_FREQ_IMULH_R 4
|
#define RANDOMX_FREQ_IMULH_R 4
|
||||||
#define RANDOMX_FREQ_IMULH_M 1
|
#define RANDOMX_FREQ_IMULH_M 1
|
||||||
#define RANDOMX_FREQ_ISMULH_R 4
|
#define RANDOMX_FREQ_ISMULH_R 4
|
||||||
#define RANDOMX_FREQ_ISMULH_M 1
|
#define RANDOMX_FREQ_ISMULH_M 1
|
||||||
#define RANDOMX_FREQ_IMUL_RCP 8
|
#define RANDOMX_FREQ_IMUL_RCP 8
|
||||||
#define RANDOMX_FREQ_INEG_R 2
|
#define RANDOMX_FREQ_INEG_R 2
|
||||||
#define RANDOMX_FREQ_IXOR_R 16
|
#define RANDOMX_FREQ_IXOR_R 16
|
||||||
#define RANDOMX_FREQ_IXOR_M 4
|
#define RANDOMX_FREQ_IXOR_M 4
|
||||||
#define RANDOMX_FREQ_IROR_R 10
|
#define RANDOMX_FREQ_IROR_R 10
|
||||||
#define RANDOMX_FREQ_IROL_R 0
|
#define RANDOMX_FREQ_IROL_R 0
|
||||||
#define RANDOMX_FREQ_ISWAP_R 4
|
#define RANDOMX_FREQ_ISWAP_R 4
|
||||||
|
|
||||||
#define RANDOMX_FREQ_FSWAP_R 8
|
#define RANDOMX_FREQ_FSWAP_R 8
|
||||||
#define RANDOMX_FREQ_FADD_R 20
|
#define RANDOMX_FREQ_FADD_R 20
|
||||||
#define RANDOMX_FREQ_FADD_M 5
|
#define RANDOMX_FREQ_FADD_M 5
|
||||||
#define RANDOMX_FREQ_FSUB_R 20
|
#define RANDOMX_FREQ_FSUB_R 20
|
||||||
#define RANDOMX_FREQ_FSUB_M 5
|
#define RANDOMX_FREQ_FSUB_M 5
|
||||||
#define RANDOMX_FREQ_FSCAL_R 6
|
#define RANDOMX_FREQ_FSCAL_R 6
|
||||||
#define RANDOMX_FREQ_FMUL_R 20
|
#define RANDOMX_FREQ_FMUL_R 20
|
||||||
#define RANDOMX_FREQ_FDIV_M 4
|
#define RANDOMX_FREQ_FDIV_M 4
|
||||||
#define RANDOMX_FREQ_FSQRT_R 6
|
#define RANDOMX_FREQ_FSQRT_R 6
|
||||||
|
|
||||||
#define RANDOMX_FREQ_COND_R 7
|
#define RANDOMX_FREQ_COND_R 7
|
||||||
#define RANDOMX_FREQ_COND_M 1
|
#define RANDOMX_FREQ_COND_M 1
|
||||||
#define RANDOMX_FREQ_CFROUND 1
|
#define RANDOMX_FREQ_CFROUND 1
|
||||||
#define RANDOMX_FREQ_ISTORE 16
|
#define RANDOMX_FREQ_ISTORE 16
|
||||||
|
|
||||||
#define RANDOMX_FREQ_NOP 0
|
#define RANDOMX_FREQ_NOP 0
|
||||||
|
/* ------
|
||||||
|
256
|
||||||
|
*/
|
||||||
|
@ -21,6 +21,7 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
#include "dataset.hpp"
|
#include "dataset.hpp"
|
||||||
@ -39,7 +40,7 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
namespace RandomX {
|
namespace RandomX {
|
||||||
|
|
||||||
void initBlock(const uint8_t* cache, uint8_t* out, uint32_t blockNumber) {
|
void initBlock(const Cache& cache, uint8_t* out, uint64_t blockNumber) {
|
||||||
uint64_t c0, c1, c2, c3, c4, c5, c6, c7;
|
uint64_t c0, c1, c2, c3, c4, c5, c6, c7;
|
||||||
|
|
||||||
c0 = 4ULL * blockNumber;
|
c0 = 4ULL * blockNumber;
|
||||||
@ -48,7 +49,15 @@ namespace RandomX {
|
|||||||
constexpr uint32_t mask = (CacheSize - 1) & CacheLineAlignMask;
|
constexpr uint32_t mask = (CacheSize - 1) & CacheLineAlignMask;
|
||||||
|
|
||||||
for (auto i = 0; i < RANDOMX_CACHE_ACCESSES; ++i) {
|
for (auto i = 0; i < RANDOMX_CACHE_ACCESSES; ++i) {
|
||||||
const uint8_t* mixBlock = cache + (c0 & mask);
|
const uint8_t* mixBlock;
|
||||||
|
if (RANDOMX_ARGON_GROWTH == 0) {
|
||||||
|
constexpr uint32_t mask = (RANDOMX_ARGON_MEMORY * ArgonBlockSize / CacheLineSize - 1);
|
||||||
|
mixBlock = cache.memory + (c0 & mask) * CacheLineSize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const uint32_t modulus = cache.size / CacheLineSize;
|
||||||
|
mixBlock = cache.memory + (c0 % modulus) * CacheLineSize;
|
||||||
|
}
|
||||||
PREFETCHNTA(mixBlock);
|
PREFETCHNTA(mixBlock);
|
||||||
c0 = squareHash(c0);
|
c0 = squareHash(c0);
|
||||||
c0 ^= load64(mixBlock + 0);
|
c0 ^= load64(mixBlock + 0);
|
||||||
@ -72,11 +81,11 @@ namespace RandomX {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void datasetRead(addr_t addr, MemoryRegisters& memory, RegisterFile& reg) {
|
void datasetRead(addr_t addr, MemoryRegisters& memory, RegisterFile& reg) {
|
||||||
uint64_t* datasetLine = (uint64_t*)(memory.ds.dataset + memory.ma);
|
uint64_t* datasetLine = (uint64_t*)(memory.ds.dataset.memory + memory.ma);
|
||||||
memory.mx ^= addr;
|
memory.mx ^= addr;
|
||||||
memory.mx &= -64; //align to cache line
|
memory.mx &= -64; //align to cache line
|
||||||
std::swap(memory.mx, memory.ma);
|
std::swap(memory.mx, memory.ma);
|
||||||
PREFETCHNTA(memory.ds.dataset + memory.ma);
|
PREFETCHNTA(memory.ds.dataset.memory + memory.ma);
|
||||||
for (int i = 0; i < RegistersCount; ++i)
|
for (int i = 0; i < RegistersCount; ++i)
|
||||||
reg.r[i] ^= datasetLine[i];
|
reg.r[i] ^= datasetLine[i];
|
||||||
}
|
}
|
||||||
@ -84,9 +93,9 @@ namespace RandomX {
|
|||||||
void datasetReadLight(addr_t addr, MemoryRegisters& memory, int_reg_t (®)[RegistersCount]) {
|
void datasetReadLight(addr_t addr, MemoryRegisters& memory, int_reg_t (®)[RegistersCount]) {
|
||||||
memory.mx ^= addr;
|
memory.mx ^= addr;
|
||||||
memory.mx &= CacheLineAlignMask; //align to cache line
|
memory.mx &= CacheLineAlignMask; //align to cache line
|
||||||
Cache* cache = memory.ds.cache;
|
Cache& cache = memory.ds.cache;
|
||||||
uint64_t datasetLine[CacheLineSize / sizeof(uint64_t)];
|
uint64_t datasetLine[CacheLineSize / sizeof(uint64_t)];
|
||||||
initBlock(cache->getCache(), (uint8_t*)datasetLine, memory.ma / CacheLineSize);
|
initBlock(cache, (uint8_t*)datasetLine, memory.ma / CacheLineSize);
|
||||||
for (int i = 0; i < RegistersCount; ++i)
|
for (int i = 0; i < RegistersCount; ++i)
|
||||||
reg[i] ^= datasetLine[i];
|
reg[i] ^= datasetLine[i];
|
||||||
std::swap(memory.mx, memory.ma);
|
std::swap(memory.mx, memory.ma);
|
||||||
@ -103,28 +112,28 @@ namespace RandomX {
|
|||||||
aw->prepareBlock(memory.ma);
|
aw->prepareBlock(memory.ma);
|
||||||
}
|
}
|
||||||
|
|
||||||
void datasetAlloc(dataset_t& ds, uint64_t size, bool largePages) {
|
void datasetAlloc(dataset_t& ds, bool largePages) {
|
||||||
if (sizeof(size_t) <= 4)
|
if (std::numeric_limits<size_t>::max() < RANDOMX_DATASET_SIZE)
|
||||||
throw std::runtime_error("Platform doesn't support enough memory for the dataset");
|
throw std::runtime_error("Platform doesn't support enough memory for the dataset");
|
||||||
if (largePages) {
|
if (largePages) {
|
||||||
ds.dataset = (uint8_t*)allocLargePagesMemory(size);
|
ds.dataset.memory = (uint8_t*)allocLargePagesMemory(ds.dataset.size);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ds.dataset = (uint8_t*)_mm_malloc(size, 64);
|
ds.dataset.memory = (uint8_t*)_mm_malloc(ds.dataset.size, 64);
|
||||||
if (ds.dataset == nullptr) {
|
if (ds.dataset.memory == nullptr) {
|
||||||
throw std::runtime_error("Dataset memory allocation failed. >4 GiB of free virtual memory is needed.");
|
throw std::runtime_error("Dataset memory allocation failed. >4 GiB of free virtual memory is needed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void datasetInit(Cache* cache, dataset_t ds, uint32_t startBlock, uint32_t blockCount) {
|
void datasetInit(Cache& cache, Dataset& ds, uint32_t startBlock, uint32_t blockCount) {
|
||||||
for (uint32_t i = startBlock; i < startBlock + blockCount; ++i) {
|
for (uint64_t i = startBlock; i < startBlock + blockCount; ++i) {
|
||||||
initBlock(cache->getCache(), ds.dataset + i * CacheLineSize, i);
|
initBlock(cache, ds.memory + i * CacheLineSize, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void datasetInitCache(const void* seed, dataset_t& ds, bool largePages) {
|
void datasetInitCache(const void* seed, dataset_t& ds, bool largePages) {
|
||||||
ds.cache = new(Cache::alloc(largePages)) Cache();
|
ds.cache.memory = allocCache(ds.cache.size, largePages);
|
||||||
ds.cache->initialize(seed, SeedSize);
|
argonFill(ds.cache, seed, SeedSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,14 +25,11 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
namespace RandomX {
|
namespace RandomX {
|
||||||
|
|
||||||
template<bool soft, bool enc>
|
void initBlock(const Cache& cache, uint8_t* out, uint64_t blockNumber);
|
||||||
void initBlock(const uint8_t* in, uint8_t* out, uint32_t blockNumber);
|
|
||||||
|
|
||||||
void initBlock(const uint8_t* cache, uint8_t* block, uint32_t blockNumber);
|
void datasetAlloc(dataset_t& ds, bool largePages);
|
||||||
|
|
||||||
void datasetAlloc(dataset_t& ds, uint64_t size, bool largePages);
|
void datasetInit(Cache& cache, Dataset& ds, uint32_t startBlock, uint32_t blockCount);
|
||||||
|
|
||||||
void datasetInit(Cache* cache, dataset_t ds, uint32_t startBlock, uint32_t blockCount);
|
|
||||||
|
|
||||||
void datasetRead(addr_t addr, MemoryRegisters& memory, RegisterFile&);
|
void datasetRead(addr_t addr, MemoryRegisters& memory, RegisterFile&);
|
||||||
|
|
||||||
|
29
src/main.cpp
29
src/main.cpp
@ -203,7 +203,7 @@ void mine(RandomX::VirtualMachine* vm, std::atomic<uint32_t>& atomicNonce, Atomi
|
|||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
bool softAes, genAsm, miningMode, verificationMode, help, largePages, async, genNative;
|
bool softAes, genAsm, miningMode, verificationMode, help, largePages, async, genNative;
|
||||||
int programCount, threadCount, initThreadCount;
|
int programCount, threadCount, initThreadCount, epoch;
|
||||||
|
|
||||||
readOption("--softAes", argc, argv, softAes);
|
readOption("--softAes", argc, argv, softAes);
|
||||||
readOption("--genAsm", argc, argv, genAsm);
|
readOption("--genAsm", argc, argv, genAsm);
|
||||||
@ -212,6 +212,7 @@ int main(int argc, char** argv) {
|
|||||||
readIntOption("--threads", argc, argv, threadCount, 1);
|
readIntOption("--threads", argc, argv, threadCount, 1);
|
||||||
readIntOption("--nonces", argc, argv, programCount, 1000);
|
readIntOption("--nonces", argc, argv, programCount, 1000);
|
||||||
readIntOption("--init", argc, argv, initThreadCount, 1);
|
readIntOption("--init", argc, argv, initThreadCount, 1);
|
||||||
|
readIntOption("--epoch", argc, argv, epoch, 0);
|
||||||
readOption("--largePages", argc, argv, largePages);
|
readOption("--largePages", argc, argv, largePages);
|
||||||
readOption("--async", argc, argv, async);
|
readOption("--async", argc, argv, async);
|
||||||
readOption("--genNative", argc, argv, genNative);
|
readOption("--genNative", argc, argv, genNative);
|
||||||
@ -246,6 +247,9 @@ int main(int argc, char** argv) {
|
|||||||
std::vector<RandomX::VirtualMachine*> vms;
|
std::vector<RandomX::VirtualMachine*> vms;
|
||||||
std::vector<std::thread> threads;
|
std::vector<std::thread> threads;
|
||||||
RandomX::dataset_t dataset;
|
RandomX::dataset_t dataset;
|
||||||
|
const uint64_t cacheSize = (RANDOMX_ARGON_MEMORY + RANDOMX_ARGON_GROWTH * epoch) * RandomX::ArgonBlockSize;
|
||||||
|
const uint64_t datasetSize = (RANDOMX_DATASET_SIZE + RANDOMX_DS_GROWTH * epoch);
|
||||||
|
dataset.cache.size = cacheSize;
|
||||||
|
|
||||||
std::cout << "RandomX - " << (miningMode ? "mining" : "verification") << " mode" << std::endl;
|
std::cout << "RandomX - " << (miningMode ? "mining" : "verification") << " mode" << std::endl;
|
||||||
|
|
||||||
@ -259,33 +263,34 @@ int main(int argc, char** argv) {
|
|||||||
RandomX::datasetInitCache(seed, dataset, largePages);
|
RandomX::datasetInitCache(seed, dataset, largePages);
|
||||||
if (RandomX::trace) {
|
if (RandomX::trace) {
|
||||||
std::cout << "Cache: " << std::endl;
|
std::cout << "Cache: " << std::endl;
|
||||||
outputHex(std::cout, (char*)dataset.cache->getCache(), sizeof(__m128i));
|
outputHex(std::cout, (char*)dataset.cache.memory, sizeof(__m128i));
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
if (!miningMode) {
|
if (!miningMode) {
|
||||||
std::cout << "Cache (256 MiB) initialized in " << sw.getElapsed() << " s" << std::endl;
|
std::cout << "Cache (" << cacheSize << " bytes) initialized in " << sw.getElapsed() << " s" << std::endl;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RandomX::Cache* cache = dataset.cache;
|
auto cache = dataset.cache;
|
||||||
RandomX::datasetAlloc(dataset, RANDOMX_DATASET_SIZE, largePages);
|
dataset.dataset.size = datasetSize;
|
||||||
const uint64_t datasetBlockCount = RANDOMX_DATASET_SIZE / RandomX::CacheLineSize;
|
RandomX::datasetAlloc(dataset, largePages);
|
||||||
|
const uint64_t datasetBlockCount = datasetSize / RandomX::CacheLineSize;
|
||||||
if (initThreadCount > 1) {
|
if (initThreadCount > 1) {
|
||||||
auto perThread = datasetBlockCount / initThreadCount;
|
auto perThread = datasetBlockCount / initThreadCount;
|
||||||
auto remainder = datasetBlockCount % initThreadCount;
|
auto remainder = datasetBlockCount % initThreadCount;
|
||||||
for (int i = 0; i < initThreadCount; ++i) {
|
for (int i = 0; i < initThreadCount; ++i) {
|
||||||
auto count = perThread + (i == initThreadCount - 1 ? remainder : 0);
|
auto count = perThread + (i == initThreadCount - 1 ? remainder : 0);
|
||||||
threads.push_back(std::thread(&RandomX::datasetInit, cache, dataset, i * perThread, count));
|
threads.push_back(std::thread(&RandomX::datasetInit, std::ref(cache), std::ref(dataset.dataset), i * perThread, count));
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < threads.size(); ++i) {
|
for (unsigned i = 0; i < threads.size(); ++i) {
|
||||||
threads[i].join();
|
threads[i].join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RandomX::datasetInit(cache, dataset, 0, datasetBlockCount);
|
RandomX::datasetInit(cache, dataset.dataset, 0, datasetBlockCount);
|
||||||
}
|
}
|
||||||
RandomX::Cache::dealloc(cache, largePages);
|
RandomX::deallocCache(cache, largePages);
|
||||||
threads.clear();
|
threads.clear();
|
||||||
std::cout << "Dataset (4 GiB) initialized in " << sw.getElapsed() << " s" << std::endl;
|
std::cout << "Dataset (" << datasetSize << " bytes) initialized in " << sw.getElapsed() << " s" << std::endl;
|
||||||
}
|
}
|
||||||
std::cout << "Initializing " << threadCount << " virtual machine(s) ..." << std::endl;
|
std::cout << "Initializing " << threadCount << " virtual machine(s) ..." << std::endl;
|
||||||
for (int i = 0; i < threadCount; ++i) {
|
for (int i = 0; i < threadCount; ++i) {
|
||||||
@ -296,7 +301,7 @@ int main(int argc, char** argv) {
|
|||||||
else {
|
else {
|
||||||
vm = new RandomX::InterpretedVirtualMachine(softAes, async);
|
vm = new RandomX::InterpretedVirtualMachine(softAes, async);
|
||||||
}
|
}
|
||||||
vm->setDataset(dataset);
|
vm->setDataset(dataset, datasetSize);
|
||||||
vms.push_back(vm);
|
vms.push_back(vm);
|
||||||
}
|
}
|
||||||
uint8_t* scratchpadMem;
|
uint8_t* scratchpadMem;
|
||||||
@ -331,7 +336,7 @@ int main(int argc, char** argv) {
|
|||||||
std::cout << "Calculated result: ";
|
std::cout << "Calculated result: ";
|
||||||
result.print(std::cout);
|
result.print(std::cout);
|
||||||
if(programCount == 1000)
|
if(programCount == 1000)
|
||||||
std::cout << "Reference result: 128599cc10f9f6251e7917fa1d09ab2116ab4081bf1357149bd4054275dd8ee9" << std::endl;
|
std::cout << "Reference result: 9c28aa1b38c55233dfa8676838db77f2ed02415ea8f7052474ce8fcdee62dcc4" << std::endl;
|
||||||
if (!miningMode) {
|
if (!miningMode) {
|
||||||
std::cout << "Performance: " << 1000 * elapsed / programCount << " ms per hash" << std::endl;
|
std::cout << "Performance: " << 1000 * elapsed / programCount << " ms per hash" << std::endl;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user