mirror of
				https://git.wownero.com/wownero/RandomWOW.git
				synced 2024-08-15 00:23:14 +00:00 
			
		
		
		
	Updated documentation and test vectors
Added AesGenerator1R test Added benchmark hints if large pages fail
This commit is contained in:
		
							parent
							
								
									91cd35ff13
								
							
						
					
					
						commit
						8282413154
					
				
					 5 changed files with 67 additions and 23 deletions
				
			
		|  | @ -157,7 +157,11 @@ The IADD_RS instruction utilizes the address calculation logic of CPUs and can b | |||
| 
 | ||||
| Because integer division is not fully pipelined in CPUs and can be made faster in ASICs, the IMUL_RCP instruction requires only one division per program to calculate the reciprocal. This forces an ASIC to include a hardware divider without giving them a performance advantage during program execution. | ||||
| 
 | ||||
| #### 2.4.3 ISWAP_R | ||||
| #### 2.4.3 IROR_R/IROL_R | ||||
| 
 | ||||
| Rotation instructions are split between rotate right and rotate left with a 4:1 ratio. Rotate right has a higher frequency because some architecures (like ARM) don't support rotate left natively (it must be emulated using rotate right). | ||||
| 
 | ||||
| #### 2.4.4 ISWAP_R | ||||
| 
 | ||||
| This instruction can be executed efficiently by CPUs that support register renaming/move elimination. | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										12
									
								
								doc/specs.md
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								doc/specs.md
									
										
									
									
									
								
							|  | @ -567,8 +567,8 @@ For integer instructions, the destination is always an integer register (registe | |||
| |2/256|INEG_R|R|-|-|`dst = -dst`| | ||||
| |15/256|IXOR_R|R|R|`src = imm32`|`dst = dst ^ src`| | ||||
| |5/256|IXOR_M|R|R|`src = 0`|`dst = dst ^ [mem]`| | ||||
| |10/256|IROR_R|R|R|`src = imm32`|`dst = dst >>> src`| | ||||
| |0/256|IROL_R|R|R|`src = imm32`|`dst = dst <<< src`| | ||||
| |8/256|IROR_R|R|R|`src = imm32`|`dst = dst >>> src`| | ||||
| |2/256|IROL_R|R|R|`src = imm32`|`dst = dst <<< src`| | ||||
| |4/256|ISWAP_R|R|R|`src = dst`|`temp = src; src = dst; dst = temp`| | ||||
| 
 | ||||
| #### 5.2.1 IADD_RS | ||||
|  | @ -616,13 +616,13 @@ All floating point operations are rounded according to the current value of the | |||
| 
 | ||||
| |frequency|instruction|dst|src|operation| | ||||
| |-|-|-|-|-| | ||||
| |8/256|FSWAP_R|F+E|-|`(dst0, dst1) = (dst1, dst0)`| | ||||
| |20/256|FADD_R|F|A|`(dst0, dst1) = (dst0 + src0, dst1 + src1)`| | ||||
| |4/256|FSWAP_R|F+E|-|`(dst0, dst1) = (dst1, dst0)`| | ||||
| |16/256|FADD_R|F|A|`(dst0, dst1) = (dst0 + src0, dst1 + src1)`| | ||||
| |5/256|FADD_M|F|R|`(dst0, dst1) = (dst0 + [mem][0], dst1 + [mem][1])`| | ||||
| |20/256|FSUB_R|F|A|`(dst0, dst1) = (dst0 - src0, dst1 - src1)`| | ||||
| |16/256|FSUB_R|F|A|`(dst0, dst1) = (dst0 - src0, dst1 - src1)`| | ||||
| |5/256|FSUB_M|F|R|`(dst0, dst1) = (dst0 - [mem][0], dst1 - [mem][1])`| | ||||
| |6/256|FSCAL_R|F|-|<code>(dst0, dst1) = (-2<sup>x0</sup> * dst0, -2<sup>x1</sup> * dst1)</code>| | ||||
| |20/256|FMUL_R|E|A|`(dst0, dst1) = (dst0 * src0, dst1 * src1)`| | ||||
| |32/256|FMUL_R|E|A|`(dst0, dst1) = (dst0 * src0, dst1 * src1)`| | ||||
| |4/256|FDIV_M|E|R|`(dst0, dst1) = (dst0 / [mem][0], dst1 / [mem][1])`| | ||||
| |6/256|FSQRT_R|E|-|`(dst0, dst1) = (√dst0, √dst1)`| | ||||
| 
 | ||||
|  |  | |||
|  | @ -38,6 +38,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| #include "utility.hpp" | ||||
| #include "../randomx.h" | ||||
| #include "../blake2/endian.h" | ||||
| #include "../common.hpp" | ||||
| #ifdef _WIN32 | ||||
| #include <windows.h> | ||||
| #include <VersionHelpers.h> | ||||
| #endif | ||||
| 
 | ||||
| const uint8_t blockTemplate_[] = { | ||||
| 		0x07, 0x07, 0xf7, 0xa4, 0xf0, 0xd6, 0x05, 0xb3, 0x03, 0x26, 0x08, 0x16, 0xba, 0x3f, 0x10, 0x90, 0x2e, 0x1a, 0x14, | ||||
|  | @ -84,6 +89,19 @@ void printUsage(const char* executable) { | |||
| 	std::cout << "  --seed S      seed for cache initialization (default: 0)" << std::endl; | ||||
| } | ||||
| 
 | ||||
| struct MemoryException : public std::exception { | ||||
| }; | ||||
| struct CacheAllocException : public MemoryException { | ||||
| 	const char * what() const throw () { | ||||
| 		return "Cache allocation failed"; | ||||
| 	} | ||||
| }; | ||||
| struct DatasetAllocException : public MemoryException { | ||||
| 	const char * what() const throw () { | ||||
| 		return "Dataset allocation failed"; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| void mine(randomx_vm* vm, std::atomic<uint32_t>& atomicNonce, AtomicHash& result, uint32_t noncesCount, int thread) { | ||||
| 	uint64_t hash[RANDOMX_HASH_SIZE / sizeof(uint64_t)]; | ||||
| 	uint8_t blockTemplate[sizeof(blockTemplate_)]; | ||||
|  | @ -118,7 +136,7 @@ int main(int argc, char** argv) { | |||
| 
 | ||||
| 	store32(&seed, seedValue); | ||||
| 
 | ||||
| 	std::cout << "RandomX benchmark" << std::endl; | ||||
| 	std::cout << "RandomX benchmark v1.0.4" << std::endl; | ||||
| 
 | ||||
| 	if (help || (!miningMode && !verificationMode)) { | ||||
| 		printUsage(argv[0]); | ||||
|  | @ -171,19 +189,20 @@ int main(int argc, char** argv) { | |||
| 	std::cout << " ..." << std::endl; | ||||
| 
 | ||||
| 	try { | ||||
| 		if (jit && !RANDOMX_HAVE_COMPILER) { | ||||
| 			throw std::runtime_error("JIT compilation is not supported on this platform"); | ||||
| 		} | ||||
| 
 | ||||
| 		Stopwatch sw(true); | ||||
| 		cache = randomx_alloc_cache(flags); | ||||
| 		if (cache == nullptr) { | ||||
| 			if (jit) { | ||||
| 				throw std::runtime_error("JIT compilation is not supported or cache allocation failed"); | ||||
| 			} | ||||
| 			throw std::runtime_error("Cache allocation failed"); | ||||
| 			throw CacheAllocException(); | ||||
| 		} | ||||
| 		randomx_init_cache(cache, &seed, sizeof(seed)); | ||||
| 		if (miningMode) { | ||||
| 			dataset = randomx_alloc_dataset(flags); | ||||
| 			if (dataset == nullptr) { | ||||
| 				throw std::runtime_error("Dataset allocation failed"); | ||||
| 				throw DatasetAllocException(); | ||||
| 			} | ||||
| 			uint32_t datasetItemCount = randomx_dataset_item_count(); | ||||
| 			if (initThreadCount > 1) { | ||||
|  | @ -241,7 +260,7 @@ int main(int argc, char** argv) { | |||
| 		std::cout << "Calculated result: "; | ||||
| 		result.print(std::cout); | ||||
| 		if (noncesCount == 1000 && seedValue == 0) | ||||
| 			std::cout << "Reference result:  a925d346195ef38048e714709e0b24a88fef565fa02fa97127e00fac08ee6eb8" << std::endl; | ||||
| 			std::cout << "Reference result:  38d47ea494480bff8d621189e8e92747288bb1da6c75dc401f2ab4b6807b6010" << std::endl; | ||||
| 		if (!miningMode) { | ||||
| 			std::cout << "Performance: " << 1000 * elapsed / noncesCount << " ms per hash" << std::endl; | ||||
| 		} | ||||
|  | @ -249,6 +268,20 @@ int main(int argc, char** argv) { | |||
| 			std::cout << "Performance: " << noncesCount / elapsed << " hashes per second" << std::endl; | ||||
| 		} | ||||
| 	} | ||||
| 	catch (MemoryException& e) { | ||||
| 		std::cout << "ERROR: " << e.what() << std::endl; | ||||
| 		if (largePages) { | ||||
| #ifdef _WIN32 | ||||
| 			std::cout << "To use large pages, please enable the \"Lock Pages in Memory\" policy and reboot." << std::endl; | ||||
| 			if (!IsWindows8OrGreater()) { | ||||
| 				std::cout << "Additionally, you have to run the benchmark from elevated command prompt." << std::endl; | ||||
| 			} | ||||
| #else | ||||
| 			std::cout << "To use large pages, please run: sudo sysctl -w vm.nr_hugepages=1250" << std::endl; | ||||
| #endif | ||||
| 		} | ||||
| 		return 1; | ||||
| 	} | ||||
| 	catch (std::exception& e) { | ||||
| 		std::cout << "ERROR: " << e.what() << std::endl; | ||||
| 		return 1; | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include "../reciprocal.h" | ||||
| #include "../intrin_portable.h" | ||||
| #include "../jit_compiler.hpp" | ||||
| #include "../aes_hash.hpp" | ||||
| 
 | ||||
| struct CacheKey { | ||||
| 	void* key; | ||||
|  | @ -146,6 +147,13 @@ int main() { | |||
| 		assert(datasetItem[0] == 0x145a5091f7853099); | ||||
| 	}); | ||||
| 
 | ||||
| 	runTest("AesGenerator1R", true, []() { | ||||
| 		char state[64] = { 0 }; | ||||
| 		hex2bin("6c19536eb2de31b6c0065f7f116e86f960d8af0c57210a6584c3237b9d064dc7", 64, state); | ||||
| 		fillAes1Rx4<true>(state, sizeof(state), state); | ||||
| 		assert(equalsHex(state, "fa89397dd6ca422513aeadba3f124b5540324c4ad4b6db434394307a17c833ab")); | ||||
| 	}); | ||||
| 
 | ||||
| 	runTest("randomx_reciprocal", true, []() { | ||||
| 		assert(randomx_reciprocal(3) == 12297829382473034410U); | ||||
| 		assert(randomx_reciprocal(13) == 11351842506898185609U); | ||||
|  | @ -959,35 +967,34 @@ int main() { | |||
| 	auto test_a = [&] { | ||||
| 		char hash[RANDOMX_HASH_SIZE]; | ||||
| 		calcStringHash("test key 000", "This is a test", &hash); | ||||
| 		assert(equalsHex(hash, "207d7cedf2a16590bd33d758e413ad129ce9888e05417984f46296252a7ba3d0")); | ||||
| 		assert(equalsHex(hash, "b33f8d10a8655d6f1925e3754adeb0a6da4c2f48a81cd4c220a412f1ef016a15")); | ||||
| 	}; | ||||
| 
 | ||||
| 	auto test_b = [&] { | ||||
| 		char hash[RANDOMX_HASH_SIZE]; | ||||
| 		calcStringHash("test key 000", "Lorem ipsum dolor sit amet", &hash); | ||||
| 		assert(equalsHex(hash, "76dd2da840d56d38153e0beaca33e7f862c5ead91a052380d99f3a62bf84579b")); | ||||
| 		assert(equalsHex(hash, "62ac336786ad3a7aff990beb2f643bd748d81dba585a52149d0baebdea0e9823")); | ||||
| 	}; | ||||
| 
 | ||||
| 	auto test_c = [&] { | ||||
| 		char hash[RANDOMX_HASH_SIZE]; | ||||
| 		calcStringHash("test key 000", "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua", &hash); | ||||
| 		assert(equalsHex(hash, "109f6a405efe09d302336dce4389127e33aa62d4c782aca7797a628e87839a61")); | ||||
| 		assert(equalsHex(hash, "6c550ebe765f7b784d2c183552fbb6048b58f17a3f115baf2b968724eb2f7a23")); | ||||
| 	}; | ||||
| 
 | ||||
| 	auto test_d = [&] { | ||||
| 		char hash[RANDOMX_HASH_SIZE]; | ||||
| 		calcStringHash("test key 001", "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua", &hash); | ||||
| 		assert(equalsHex(hash, "3cbb82edf9541ab80233cdc47384cea719c8567a8bbaca8f3ff038488ce9c16c")); | ||||
| 		assert(equalsHex(hash, "cb602b9c498b67e31e519fbdc07e288de46f949b14ad620380df6250eaffbd4e")); | ||||
| 	}; | ||||
| 
 | ||||
| 	auto test_e = [&] { | ||||
| 		char hash[RANDOMX_HASH_SIZE]; | ||||
| 		calcHexHash("test key 001", "0b0b98bea7e805e0010a2126d287a2a0cc833d312cb786385a7c2f9de69d25537f584a9bc9977b00000000666fd8753bf61a8631f12984e3fd44f4014eca629276817b56f32e9b68bd82f416", &hash); | ||||
| 
 | ||||
| 		//std::cout << std::endl;
 | ||||
| 		//outputHex(std::cout, (const char*)hash, sizeof(hash));
 | ||||
| 		//std::cout << std::endl;
 | ||||
| 
 | ||||
| 		assert(equalsHex(hash, "e003ef128b1f96d99d4a0490e03253ef11186002a8ec018cbd4e07b8ec8c82e8")); | ||||
| 		assert(equalsHex(hash, "f60caf300917760337e8ce51487484e6a33d4aaa15aa79c985efb4ea00390918")); | ||||
| 	}; | ||||
| 
 | ||||
| 	runTest("Hash test 1a (interpreter)", stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_a); | ||||
|  |  | |||
|  | @ -52,7 +52,7 @@ char parseNibble(char hex) { | |||
| 	return hex; | ||||
| } | ||||
| 
 | ||||
| void hex2bin(char *in, int length, char *out) { | ||||
| void hex2bin(const char *in, int length, char *out) { | ||||
| 	for (int i = 0; i < length; i += 2) { | ||||
| 		char nibble1 = parseNibble(*in++); | ||||
| 		char nibble2 = parseNibble(*in++); | ||||
|  | @ -67,7 +67,7 @@ constexpr bool stringsEqual(char const * a, char const * b) { | |||
| template<size_t N> | ||||
| bool equalsHex(const void* hash, const char (&hex)[N]) { | ||||
| 	char reference[N / 2]; | ||||
| 	hex2bin((char*)hex, N - 1, reference); | ||||
| 	hex2bin(hex, N - 1, reference); | ||||
| 	return memcmp(hash, reference, sizeof(reference)) == 0; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue