Kaynağa Gözat

Flags ordered by their impact on performance
Additional error handling

tevador 7 yıl önce
ebeveyn
işleme
bc78b628ea

+ 5 - 1
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<http://www.gnu.org/licenses/>.
 */
 
+#include <new>
 #include "allocator.hpp"
 #include "intrin_portable.h"
 #include "virtual_memory.hpp"
@@ -26,7 +27,10 @@ namespace randomx {
 
 	template<size_t alignment>
 	void* AlignedAllocator<alignment>::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<size_t alignment>

+ 24 - 18
src/randomx.cpp

@@ -28,7 +28,7 @@ along with RandomX.  If not, see<http://www.gnu.org/licenses/>.
 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) {

+ 5 - 5
src/randomx.h

@@ -27,10 +27,10 @@ along with RandomX.  If not, see<http://www.gnu.org/licenses/>.
 
 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);

+ 1 - 2
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);
 

+ 1 - 2
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);
 

+ 5 - 5
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;

+ 12 - 2
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<http://www.gnu.org/licenses/>.
 */
 
+#include <cstring>
+#include <iomanip>
+#include <stdexcept>
 #include "virtual_machine.hpp"
 #include "common.hpp"
 #include "aes_hash.hpp"
 #include "blake2/blake2.h"
-#include <cstring>
-#include <iomanip>
 #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<class Allocator, bool softAes>
 	VmBase<Allocator, softAes>::~VmBase() {
 		Allocator::freeMemory(scratchpad, ScratchpadSize);
@@ -100,6 +103,13 @@ namespace randomx {
 
 	template<class Allocator, bool softAes>
 	void VmBase<Allocator, softAes>::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);
 	}
 

+ 1 - 1
src/vm_compiled_light.hpp

@@ -37,7 +37,7 @@ namespace randomx {
 			AlignedAllocator<CacheLineSize>::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<Allocator, softAes>::mem;