mirror of
				https://git.wownero.com/wownero/RandomWOW.git
				synced 2024-08-15 00:23:14 +00:00 
			
		
		
		
	benchmark: add thread affinity setting
This commit is contained in:
		
							parent
							
								
									7edae5a4e4
								
							
						
					
					
						commit
						81d3a9d4a1
					
				
					 5 changed files with 190 additions and 6 deletions
				
			
		
							
								
								
									
										11
									
								
								makefile
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								makefile
									
										
									
									
									
								
							|  | @ -2,6 +2,7 @@ | |||
| #CC=gcc-8
 | ||||
| AR=gcc-ar | ||||
| PLATFORM=$(shell uname -m) | ||||
| OS=$(shell uname -s) | ||||
| CXXFLAGS=-std=c++11 | ||||
| CCFLAGS=-std=c99 | ||||
| ARFLAGS=rcs | ||||
|  | @ -21,6 +22,9 @@ ifeq ($(PLATFORM),x86_64) | |||
|     RXOBJS += $(addprefix $(OBJDIR)/,jit_compiler_x86_static.o jit_compiler_x86.o) | ||||
|     CXXFLAGS += -maes | ||||
| endif | ||||
| ifeq ($(OS),Darwin) | ||||
|     AR=ar | ||||
| endif | ||||
| 
 | ||||
| release: CXXFLAGS += -O3 -flto | ||||
| release: CCFLAGS += -O3 -flto | ||||
|  | @ -54,10 +58,10 @@ $(OBJDIR): | |||
| $(BINDIR): | ||||
| 	mkdir $(BINDIR) | ||||
| $(OBJDIR)/benchmark.o: $(TESTDIR)/benchmark.cpp $(TESTDIR)/stopwatch.hpp \ | ||||
|  $(TESTDIR)/utility.hpp $(SRCDIR)/randomx.h $(SRCDIR)/blake2/endian.h | ||||
|  $(TESTDIR)/utility.hpp $(SRCDIR)/randomx.h $(SRCDIR)/blake2/endian.h $(SRCDIR)/affinity.hpp | ||||
| 	$(CXX) $(CXXFLAGS) -pthread -c $< -o $@ | ||||
| $(BINDIR)/benchmark: $(OBJDIR)/benchmark.o $(RXA) | ||||
| 	$(CXX) $(LDFLAGS) -pthread $< $(RXA) -o $@ | ||||
| $(BINDIR)/benchmark: $(OBJDIR)/benchmark.o $(OBJDIR)/affinity.o $(RXA) | ||||
| 	$(CXX) $(LDFLAGS) -pthread $< $(OBJDIR)/affinity.o $(RXA) -o $@ | ||||
| $(OBJDIR)/code-generator.o: $(TESTDIR)/code-generator.cpp $(TESTDIR)/utility.hpp \ | ||||
|  $(SRCDIR)/common.hpp $(SRCDIR)/blake2/endian.h \
 | ||||
|  $(SRCDIR)/configuration.h $(SRCDIR)/randomx.h \
 | ||||
|  | @ -105,6 +109,7 @@ $(OBJDIR)/vm_interpreted.o: $(SRCDIR)/vm_interpreted.cpp $(SRCDIR)/vm_interprete | |||
|  $(SRCDIR)/intrin_portable.h $(SRCDIR)/allocator.hpp $(SRCDIR)/dataset.hpp \
 | ||||
|  $(SRCDIR)/superscalar_program.hpp $(SRCDIR)/jit_compiler_x86.hpp $(SRCDIR)/reciprocal.h \
 | ||||
|  $(SRCDIR)/instruction_weights.hpp | ||||
| $(OBJDIR/affinity.o: $(SRCDIR)/affinity.cpp $(SRCDIR)/affinity.hpp | ||||
| $(OBJDIR)/allocator.o: $(SRCDIR)/allocator.cpp $(SRCDIR)/allocator.hpp $(SRCDIR)/intrin_portable.h \ | ||||
|  $(SRCDIR)/virtual_memory.hpp $(SRCDIR)/common.hpp $(SRCDIR)/blake2/endian.h \
 | ||||
|  $(SRCDIR)/configuration.h $(SRCDIR)/randomx.h | ||||
|  |  | |||
							
								
								
									
										114
									
								
								src/affinity.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								src/affinity.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,114 @@ | |||
| /*
 | ||||
| Copyright (c) 2019, jtgrassie | ||||
| 
 | ||||
| All rights reserved. | ||||
| 
 | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are met: | ||||
| 	* Redistributions of source code must retain the above copyright | ||||
| 	  notice, this list of conditions and the following disclaimer. | ||||
| 	* Redistributions in binary form must reproduce the above copyright | ||||
| 	  notice, this list of conditions and the following disclaimer in the | ||||
| 	  documentation and/or other materials provided with the distribution. | ||||
| 	* Neither the name of the copyright holder nor the | ||||
| 	  names of its contributors may be used to endorse or promote products | ||||
| 	  derived from this software without specific prior written permission. | ||||
| 
 | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
| 
 | ||||
| #if defined(_WIN32) || defined(__CYGWIN__) | ||||
|   #include <windows.h> | ||||
| #else | ||||
|   #ifdef __APPLE__ | ||||
|     #include <mach/thread_act.h> | ||||
|     #include <mach/thread_policy.h> | ||||
|   #endif | ||||
|   #include <pthread.h> | ||||
| #endif | ||||
| #include "affinity.hpp" | ||||
| 
 | ||||
| int | ||||
| set_thread_affinity(const unsigned &cpuid) | ||||
| { | ||||
|     std::thread::native_handle_type thread; | ||||
| #if defined(_WIN32) || defined(__CYGWIN__) | ||||
|     thread = static_cast<std::thread::native_handle_type>(GetCurrentThread()); | ||||
| #else | ||||
|     thread = static_cast<std::thread::native_handle_type>(pthread_self()); | ||||
| #endif | ||||
|     return set_thread_affinity(thread, cpuid); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| set_thread_affinity(std::thread::native_handle_type thread, | ||||
|         const unsigned &cpuid) | ||||
| { | ||||
|     int rc = -1; | ||||
| #ifdef __APPLE__ | ||||
|     thread_port_t mach_thread; | ||||
|     thread_affinity_policy_data_t policy = { static_cast<integer_t>(cpuid) }; | ||||
|     mach_thread = pthread_mach_thread_np(thread); | ||||
|     rc = thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, | ||||
|             (thread_policy_t)&policy, 1); | ||||
| #elif defined(_WIN32) || defined(__CYGWIN__) | ||||
|     rc = SetThreadAffinityMask(thread, 1ULL << cpuid) == 0 ? -2 : 0; | ||||
| #else | ||||
|     cpu_set_t cs; | ||||
|     CPU_ZERO(&cs); | ||||
|     CPU_SET(cpuid, &cs); | ||||
|     rc = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cs); | ||||
| #endif | ||||
|     return rc; | ||||
| } | ||||
| 
 | ||||
| unsigned | ||||
| cpuid_from_mask(uint64_t mask, const unsigned &thread_index) | ||||
| { | ||||
|     static unsigned lookup[64]; | ||||
|     static bool init = false; | ||||
|     if (init) | ||||
|         return lookup[thread_index]; | ||||
|     unsigned count_found = 0; | ||||
|     for (unsigned i=0; i<64; i++) | ||||
|     { | ||||
|         if (1ULL & mask) | ||||
|         { | ||||
|             lookup[count_found] = i; | ||||
|             count_found++; | ||||
|         } | ||||
|         mask >>= 1; | ||||
|     } | ||||
|     init = true; | ||||
|     return lookup[thread_index]; | ||||
| } | ||||
| 
 | ||||
| std::string | ||||
| mask_to_string(uint64_t mask) | ||||
| { | ||||
|     std::string r(65, '\0'); | ||||
|     unsigned len = 0; | ||||
|     unsigned v = 0; | ||||
|     unsigned i = 64; | ||||
|     while (i--) | ||||
|     { | ||||
|         v = mask >> i; | ||||
|         if (1ULL & v) | ||||
|         { | ||||
|             if (len == 0) len = i+1; | ||||
|             r[len-i] = '1'; | ||||
|         } | ||||
|         else | ||||
|             if (len > 0) r[len-i] = '0'; | ||||
|     } | ||||
|     return r; | ||||
| } | ||||
							
								
								
									
										39
									
								
								src/affinity.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/affinity.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| /*
 | ||||
| Copyright (c) 2019, jtgrassie | ||||
| 
 | ||||
| All rights reserved. | ||||
| 
 | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are met: | ||||
| 	* Redistributions of source code must retain the above copyright | ||||
| 	  notice, this list of conditions and the following disclaimer. | ||||
| 	* Redistributions in binary form must reproduce the above copyright | ||||
| 	  notice, this list of conditions and the following disclaimer in the | ||||
| 	  documentation and/or other materials provided with the distribution. | ||||
| 	* Neither the name of the copyright holder nor the | ||||
| 	  names of its contributors may be used to endorse or promote products | ||||
| 	  derived from this software without specific prior written permission. | ||||
| 
 | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <cstddef> | ||||
| #include <thread> | ||||
| #include <string> | ||||
| 
 | ||||
| int set_thread_affinity(const unsigned &cpuid); | ||||
| int set_thread_affinity(std::thread::native_handle_type thread, | ||||
|         const unsigned &cpuid); | ||||
| unsigned cpuid_from_mask(uint64_t mask, const unsigned &thread_index); | ||||
| std::string mask_to_string(uint64_t mask); | ||||
|  | @ -38,6 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| #include "utility.hpp" | ||||
| #include "../randomx.h" | ||||
| #include "../blake2/endian.h" | ||||
| #include "../affinity.hpp" | ||||
| 
 | ||||
| const uint8_t blockTemplate_[] = { | ||||
| 		0x07, 0x07, 0xf7, 0xa4, 0xf0, 0xd6, 0x05, 0xb3, 0x03, 0x26, 0x08, 0x16, 0xba, 0x3f, 0x10, 0x90, 0x2e, 0x1a, 0x14, | ||||
|  | @ -79,12 +80,19 @@ void printUsage(const char* executable) { | |||
| 	std::cout << "  --largePages  use large pages" << std::endl; | ||||
| 	std::cout << "  --softAes     use software AES (default: x86 AES-NI)" << std::endl; | ||||
| 	std::cout << "  --threads T   use T threads (default: 1)" << std::endl; | ||||
| 	std::cout << "  --affinity A  thread affinity bitmask (default: 0)" << std::endl; | ||||
| 	std::cout << "  --init Q      initialize dataset with Q threads (default: 1)" << std::endl; | ||||
| 	std::cout << "  --nonces N    run N nonces (default: 1000)" << std::endl; | ||||
| 	std::cout << "  --seed S      seed for cache initialization (default: 0)" << std::endl; | ||||
| } | ||||
| 
 | ||||
| void mine(randomx_vm* vm, std::atomic<uint32_t>& atomicNonce, AtomicHash& result, uint32_t noncesCount, int thread) { | ||||
| void mine(randomx_vm* vm, std::atomic<uint32_t>& atomicNonce, AtomicHash& result, uint32_t noncesCount, int thread, int cpuid=-1) { | ||||
| 	if (cpuid >= 0) { | ||||
| 		int rc = set_thread_affinity(cpuid); | ||||
| 		if (rc) { | ||||
| 			std::cerr << "Failed to set thread affinity for thread " << thread << " (error=" << rc << ")" <<  std::endl; | ||||
| 		} | ||||
| 	} | ||||
| 	uint64_t hash[RANDOMX_HASH_SIZE / sizeof(uint64_t)]; | ||||
| 	uint8_t blockTemplate[sizeof(blockTemplate_)]; | ||||
| 	memcpy(blockTemplate, blockTemplate_, sizeof(blockTemplate)); | ||||
|  | @ -102,6 +110,7 @@ void mine(randomx_vm* vm, std::atomic<uint32_t>& atomicNonce, AtomicHash& result | |||
| int main(int argc, char** argv) { | ||||
| 	bool softAes, miningMode, verificationMode, help, largePages, jit; | ||||
| 	int noncesCount, threadCount, initThreadCount; | ||||
| 	uint64_t threadAffinity; | ||||
| 	int32_t seedValue; | ||||
| 	char seed[4]; | ||||
| 
 | ||||
|  | @ -109,6 +118,7 @@ int main(int argc, char** argv) { | |||
| 	readOption("--mine", argc, argv, miningMode); | ||||
| 	readOption("--verify", argc, argv, verificationMode); | ||||
| 	readIntOption("--threads", argc, argv, threadCount, 1); | ||||
| 	readUInt64Option("--affinity", argc, argv, threadAffinity, 0); | ||||
| 	readIntOption("--nonces", argc, argv, noncesCount, 1000); | ||||
| 	readIntOption("--init", argc, argv, initThreadCount, 1); | ||||
| 	readIntOption("--seed", argc, argv, seedValue, 0); | ||||
|  | @ -165,6 +175,10 @@ int main(int argc, char** argv) { | |||
| 		std::cout << " - small pages mode" << std::endl; | ||||
| 	} | ||||
| 
 | ||||
| 	if (threadAffinity) { | ||||
| 		std::cout << " - thread affinity (" << mask_to_string(threadAffinity) << ")" << std::endl; | ||||
| 	} | ||||
| 
 | ||||
| 	std::cout << "Initializing"; | ||||
| 	if (miningMode) | ||||
| 		std::cout << " (" << initThreadCount << " thread" << (initThreadCount > 1 ? "s)" : ")"); | ||||
|  | @ -218,10 +232,13 @@ int main(int argc, char** argv) { | |||
| 		sw.restart(); | ||||
| 		if (threadCount > 1) { | ||||
| 			for (unsigned i = 0; i < vms.size(); ++i) { | ||||
| 				int cpuid = -1; | ||||
| 				if (threadAffinity) | ||||
| 					cpuid = cpuid_from_mask(threadAffinity, i); | ||||
| 				if (softAes) | ||||
| 					threads.push_back(std::thread(&mine, vms[i], std::ref(atomicNonce), std::ref(result), noncesCount, i)); | ||||
| 					threads.push_back(std::thread(&mine, vms[i], std::ref(atomicNonce), std::ref(result), noncesCount, i, cpuid)); | ||||
| 				else | ||||
| 					threads.push_back(std::thread(&mine, vms[i], std::ref(atomicNonce), std::ref(result), noncesCount, i)); | ||||
| 					threads.push_back(std::thread(&mine, vms[i], std::ref(atomicNonce), std::ref(result), noncesCount, i, cpuid)); | ||||
| 			} | ||||
| 			for (unsigned i = 0; i < threads.size(); ++i) { | ||||
| 				threads[i].join(); | ||||
|  |  | |||
|  | @ -66,6 +66,15 @@ inline void readIntOption(const char* option, int argc, char** argv, int& out, i | |||
| 	out = defaultValue; | ||||
| } | ||||
| 
 | ||||
| inline void readUInt64Option(const char* option, int argc, char** argv, uint64_t& out, uint64_t defaultValue) { | ||||
| 	for (int i = 0; i < argc - 1; ++i) { | ||||
| 		if (strcmp(argv[i], option) == 0 && (out = std::strtoull(argv[i + 1], NULL, 0)) > 0) { | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 	out = defaultValue; | ||||
| } | ||||
| 
 | ||||
| inline void readFloatOption(const char* option, int argc, char** argv, double& out, double defaultValue) { | ||||
| 	for (int i = 0; i < argc - 1; ++i) { | ||||
| 		if (strcmp(argv[i], option) == 0 && (out = atof(argv[i + 1])) > 0) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue