From bc78b628ea7fc01387ab3f5315f946888c439107 Mon Sep 17 00:00:00 2001 From: tevador Date: Sun, 21 Apr 2019 23:23:13 +0200 Subject: [PATCH] Flags ordered by their impact on performance Additional error handling --- src/allocator.cpp | 6 +++++- src/randomx.cpp | 42 ++++++++++++++++++++++---------------- src/randomx.h | 10 ++++----- src/tests/api-example1.c | 3 +-- src/tests/api-example2.cpp | 3 +-- src/tests/benchmark.cpp | 10 ++++----- src/virtual_machine.cpp | 14 +++++++++++-- src/vm_compiled_light.hpp | 2 +- 8 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/allocator.cpp b/src/allocator.cpp index 2626147..2c344a8 100644 --- a/src/allocator.cpp +++ b/src/allocator.cpp @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License along with RandomX. If not, see. */ +#include #include "allocator.hpp" #include "intrin_portable.h" #include "virtual_memory.hpp" @@ -26,7 +27,10 @@ namespace randomx { template void* AlignedAllocator::allocMemory(size_t count) { - return _mm_malloc(count, alignment); + void *mem = _mm_malloc(count, alignment); + if (mem == nullptr) + throw std::bad_alloc(); + return mem; } template diff --git a/src/randomx.cpp b/src/randomx.cpp index bb8aa22..cc076c1 100644 --- a/src/randomx.cpp +++ b/src/randomx.cpp @@ -28,7 +28,7 @@ along with RandomX. If not, see. extern "C" { randomx_cache *randomx_alloc_cache(randomx_flags flags) { - randomx_cache *cache; + randomx_cache *cache = nullptr; try { switch (flags & (RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES)) { @@ -99,72 +99,72 @@ extern "C" { delete dataset; } - randomx_vm *randomx_create_vm(randomx_flags flags) { + randomx_vm *randomx_create_vm(randomx_flags flags, randomx_cache *cache, randomx_dataset *dataset) { randomx_vm *vm = nullptr; try { switch (flags & (RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES)) { - case RANDOMX_FLAG_DEFAULT: //0 + case RANDOMX_FLAG_DEFAULT: vm = new randomx::InterpretedLightVmDefault(); break; - case RANDOMX_FLAG_FULL_MEM: //1 + case RANDOMX_FLAG_FULL_MEM: vm = new randomx::InterpretedVmDefault(); break; - case RANDOMX_FLAG_JIT: //2 + case RANDOMX_FLAG_JIT: vm = new randomx::CompiledLightVmDefault(); break; - case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT: //3 + case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT: vm = new randomx::CompiledVmDefault(); break; - case RANDOMX_FLAG_HARD_AES: //4 + case RANDOMX_FLAG_HARD_AES: vm = new randomx::InterpretedLightVmHardAes(); break; - case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_HARD_AES: //5 + case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_HARD_AES: vm = new randomx::InterpretedVmHardAes(); break; - case RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES: //6 + case RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES: vm = new randomx::CompiledLightVmHardAes(); break; - case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES: //7 + case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES: vm = new randomx::CompiledVmHardAes(); break; - case RANDOMX_FLAG_LARGE_PAGES: //8 + case RANDOMX_FLAG_LARGE_PAGES: vm = new randomx::InterpretedLightVmLargePage(); break; - case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_LARGE_PAGES: //9 + case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_LARGE_PAGES: vm = new randomx::InterpretedVmLargePage(); break; - case RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES: //10 + case RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES: vm = new randomx::CompiledLightVmLargePage(); break; - case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES: //11 + case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES: vm = new randomx::CompiledVmLargePage(); break; - case RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES: //12 + case RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES: vm = new randomx::InterpretedLightVmLargePageHardAes(); break; - case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES: //13 + case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES: vm = new randomx::InterpretedVmLargePageHardAes(); break; - case RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES: //14 + case RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES: vm = new randomx::CompiledLightVmLargePageHardAes(); break; - case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES: //15 + case RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES: vm = new randomx::CompiledVmLargePageHardAes(); break; @@ -172,6 +172,12 @@ extern "C" { UNREACHABLE; } + if(cache != nullptr) + vm->setCache(cache); + + if(dataset != nullptr) + vm->setDataset(dataset); + vm->allocate(); } catch (std::exception &ex) { diff --git a/src/randomx.h b/src/randomx.h index 58d9888..f620c06 100644 --- a/src/randomx.h +++ b/src/randomx.h @@ -27,10 +27,10 @@ along with RandomX. If not, see. typedef enum { RANDOMX_FLAG_DEFAULT = 0, - RANDOMX_FLAG_FULL_MEM = 1, - RANDOMX_FLAG_JIT = 2, - RANDOMX_FLAG_HARD_AES = 4, - RANDOMX_FLAG_LARGE_PAGES = 8, + RANDOMX_FLAG_LARGE_PAGES = 1, + RANDOMX_FLAG_HARD_AES = 2, + RANDOMX_FLAG_FULL_MEM = 4, + RANDOMX_FLAG_JIT = 8, } randomx_flags; typedef struct randomx_dataset randomx_dataset; @@ -49,7 +49,7 @@ randomx_dataset *randomx_alloc_dataset(randomx_flags flags); void randomx_init_dataset(randomx_dataset *dataset, randomx_cache *cache, unsigned long startBlock, unsigned long blockCount); void randomx_release_dataset(randomx_dataset *dataset); -randomx_vm *randomx_create_vm(randomx_flags flags); +randomx_vm *randomx_create_vm(randomx_flags flags, randomx_cache *cache, randomx_dataset *dataset); void randomx_vm_set_cache(randomx_vm *machine, randomx_cache* cache); void randomx_vm_set_dataset(randomx_vm *machine, randomx_dataset *dataset); void randomx_destroy_vm(randomx_vm *machine); diff --git a/src/tests/api-example1.c b/src/tests/api-example1.c index f8277b9..7de0db2 100644 --- a/src/tests/api-example1.c +++ b/src/tests/api-example1.c @@ -8,8 +8,7 @@ int main() { randomx_cache *myCache = randomx_alloc_cache(RANDOMX_FLAG_DEFAULT); randomx_init_cache(myCache, mySeed, sizeof mySeed); - randomx_vm *myMachine = randomx_create_vm(RANDOMX_FLAG_DEFAULT); - randomx_vm_set_cache(myMachine, myCache); + randomx_vm *myMachine = randomx_create_vm(RANDOMX_FLAG_DEFAULT, myCache, NULL); randomx_calculate_hash(myMachine, &myInput, sizeof myInput, hash); diff --git a/src/tests/api-example2.cpp b/src/tests/api-example2.cpp index ebd99c4..5d78037 100644 --- a/src/tests/api-example2.cpp +++ b/src/tests/api-example2.cpp @@ -26,8 +26,7 @@ int main() { t2.join(); randomx_release_cache(myCache); - randomx_vm *myMachine = randomx_create_vm((randomx_flags)(RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES)); - randomx_vm_set_dataset(myMachine, myDataset); + randomx_vm *myMachine = randomx_create_vm((randomx_flags)(RANDOMX_FLAG_FULL_MEM | RANDOMX_FLAG_JIT | RANDOMX_FLAG_HARD_AES | RANDOMX_FLAG_LARGE_PAGES), nullptr, myDataset); randomx_calculate_hash(myMachine, &myInput, sizeof myInput, hash); diff --git a/src/tests/benchmark.cpp b/src/tests/benchmark.cpp index a92f9b6..f20e59c 100644 --- a/src/tests/benchmark.cpp +++ b/src/tests/benchmark.cpp @@ -201,11 +201,11 @@ int main(int argc, char** argv) { std::cout << "Memory initialized in " << sw.getElapsed() << " s" << std::endl; std::cout << "Initializing " << threadCount << " virtual machine(s) ..." << std::endl; for (int i = 0; i < threadCount; ++i) { - randomx_vm *vm = randomx_create_vm(flags); - if (miningMode) - randomx_vm_set_dataset(vm, dataset); - else - randomx_vm_set_cache(vm, cache); + randomx_vm *vm = randomx_create_vm(flags, cache, dataset); + if (vm == nullptr) { + std::cout << "ERROR: Unsupported virtual machine options" << std::endl; + return 1; + } vms.push_back(vm); } std::cout << "Running benchmark (" << noncesCount << " nonces) ..." << std::endl; diff --git a/src/virtual_machine.cpp b/src/virtual_machine.cpp index a8e2b63..a0e60cb 100644 --- a/src/virtual_machine.cpp +++ b/src/virtual_machine.cpp @@ -17,12 +17,13 @@ You should have received a copy of the GNU General Public License along with RandomX. If not, see. */ +#include +#include +#include #include "virtual_machine.hpp" #include "common.hpp" #include "aes_hash.hpp" #include "blake2/blake2.h" -#include -#include #include "intrin_portable.h" #include "allocator.hpp" @@ -93,6 +94,8 @@ std::ostream& operator<<(std::ostream& os, const randomx::RegisterFile& rf) { namespace randomx { + alignas(16) volatile static __m128i aesDummy; + template VmBase::~VmBase() { Allocator::freeMemory(scratchpad, ScratchpadSize); @@ -100,6 +103,13 @@ namespace randomx { template void VmBase::allocate() { + if (mem.memory == nullptr) + throw std::invalid_argument("Cache/Dataset not set"); + if (!softAes) { //if hardware AES is not supported, it's better to fail now than to return a ticking bomb + __m128i tmp = _mm_load_si128((const __m128i*)&aesDummy); + tmp = _mm_aesenc_si128(tmp, tmp); + _mm_store_si128((__m128i*)&aesDummy, tmp); + } scratchpad = (uint8_t*)Allocator::allocMemory(ScratchpadSize); } diff --git a/src/vm_compiled_light.hpp b/src/vm_compiled_light.hpp index 8183039..242680d 100644 --- a/src/vm_compiled_light.hpp +++ b/src/vm_compiled_light.hpp @@ -37,7 +37,7 @@ namespace randomx { AlignedAllocator::freeMemory(ptr, sizeof(CompiledLightVm)); } void setCache(randomx_cache* cache) override; - void setDataset(randomx_dataset* dataset) override {} + void setDataset(randomx_dataset* dataset) override { } void run(void* seed) override; using CompiledVm::mem;