From 7edae5a4e4db95cd142c1fb95d93b0f7852bee7e Mon Sep 17 00:00:00 2001 From: tevador Date: Tue, 11 Jun 2019 11:00:36 +0200 Subject: [PATCH 1/3] Fix possible overflow in static_assert --- src/common.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common.hpp b/src/common.hpp index 08fe7f33..e6682ffa 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -69,7 +69,7 @@ namespace randomx { static_assert(wtSum == 256, "Sum of instruction frequencies must be 256."); - constexpr int ArgonBlockSize = 1024; + constexpr uint32_t ArgonBlockSize = 1024; constexpr int ArgonSaltSize = sizeof("" RANDOMX_ARGON_SALT) - 1; constexpr int SuperscalarMaxSize = 3 * RANDOMX_SUPERSCALAR_LATENCY + 2; constexpr int CacheLineSize = RANDOMX_DATASET_ITEM_SIZE; @@ -84,7 +84,7 @@ namespace randomx { //Prevent some unsafe configurations. #ifndef RANDOMX_UNSAFE - static_assert(RANDOMX_CACHE_ACCESSES * RANDOMX_ARGON_MEMORY * ArgonBlockSize + 33554432 >= RANDOMX_DATASET_BASE_SIZE + RANDOMX_DATASET_EXTRA_SIZE, "Unsafe configuration: Memory-time tradeoffs"); + static_assert((uint64_t)ArgonBlockSize * RANDOMX_CACHE_ACCESSES * RANDOMX_ARGON_MEMORY + 33554432 >= (uint64_t)RANDOMX_DATASET_BASE_SIZE + RANDOMX_DATASET_EXTRA_SIZE, "Unsafe configuration: Memory-time tradeoffs"); static_assert((128 + RANDOMX_PROGRAM_SIZE * RANDOMX_FREQ_ISTORE / 256) * (RANDOMX_PROGRAM_COUNT * RANDOMX_PROGRAM_ITERATIONS) >= RANDOMX_SCRATCHPAD_L3, "Unsafe configuration: Insufficient Scratchpad writes"); static_assert(RANDOMX_PROGRAM_COUNT > 1, "Unsafe configuration: Program filtering strategies"); static_assert(RANDOMX_PROGRAM_SIZE >= 64, "Unsafe configuration: Low program entropy"); From 81d3a9d4a1e0f92121dc1af9cf8605e8e630ac71 Mon Sep 17 00:00:00 2001 From: Jethro Grassie Date: Wed, 12 Jun 2019 23:18:38 -0400 Subject: [PATCH 2/3] benchmark: add thread affinity setting --- makefile | 11 ++-- src/affinity.cpp | 114 ++++++++++++++++++++++++++++++++++++++++ src/affinity.hpp | 39 ++++++++++++++ src/tests/benchmark.cpp | 23 ++++++-- src/tests/utility.hpp | 9 ++++ 5 files changed, 190 insertions(+), 6 deletions(-) create mode 100644 src/affinity.cpp create mode 100644 src/affinity.hpp diff --git a/makefile b/makefile index 9d958840..cef94817 100644 --- a/makefile +++ b/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 diff --git a/src/affinity.cpp b/src/affinity.cpp new file mode 100644 index 00000000..fc05c29e --- /dev/null +++ b/src/affinity.cpp @@ -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 +#else + #ifdef __APPLE__ + #include + #include + #endif + #include +#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(GetCurrentThread()); +#else + thread = static_cast(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(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; +} diff --git a/src/affinity.hpp b/src/affinity.hpp new file mode 100644 index 00000000..db9e9a97 --- /dev/null +++ b/src/affinity.hpp @@ -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 +#include +#include + +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); diff --git a/src/tests/benchmark.cpp b/src/tests/benchmark.cpp index 73437132..5582691f 100644 --- a/src/tests/benchmark.cpp +++ b/src/tests/benchmark.cpp @@ -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& atomicNonce, AtomicHash& result, uint32_t noncesCount, int thread) { +void mine(randomx_vm* vm, std::atomic& 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& 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(); diff --git a/src/tests/utility.hpp b/src/tests/utility.hpp index a036aee0..52f97333 100644 --- a/src/tests/utility.hpp +++ b/src/tests/utility.hpp @@ -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) { From e8cf27eab5376016167f029216f68b7e0a48062e Mon Sep 17 00:00:00 2001 From: tevador Date: Sat, 22 Jun 2019 23:11:24 +0200 Subject: [PATCH 3/3] Fixed Visual Studio build Moved affinity to tests Fixed strange output from mask_to_string --- makefile | 5 +++-- src/{ => tests}/affinity.cpp | 21 ++++++++++++--------- src/{ => tests}/affinity.hpp | 0 src/tests/benchmark.cpp | 2 +- vcxproj/benchmark.vcxproj | 1 + vcxproj/benchmark.vcxproj.filters | 3 +++ 6 files changed, 20 insertions(+), 12 deletions(-) rename src/{ => tests}/affinity.cpp (93%) rename src/{ => tests}/affinity.hpp (100%) diff --git a/makefile b/makefile index cef94817..702ccd34 100644 --- a/makefile +++ b/makefile @@ -57,8 +57,10 @@ $(OBJDIR): mkdir $(OBJDIR) $(BINDIR): mkdir $(BINDIR) +$(OBJDIR)/affinity.o: $(TESTDIR)/affinity.cpp $(TESTDIR)/affinity.hpp + $(CXX) $(CXXFLAGS) -c $< -o $@ $(OBJDIR)/benchmark.o: $(TESTDIR)/benchmark.cpp $(TESTDIR)/stopwatch.hpp \ - $(TESTDIR)/utility.hpp $(SRCDIR)/randomx.h $(SRCDIR)/blake2/endian.h $(SRCDIR)/affinity.hpp + $(TESTDIR)/utility.hpp $(SRCDIR)/randomx.h $(SRCDIR)/blake2/endian.h $(TESTDIR)/affinity.hpp $(CXX) $(CXXFLAGS) -pthread -c $< -o $@ $(BINDIR)/benchmark: $(OBJDIR)/benchmark.o $(OBJDIR)/affinity.o $(RXA) $(CXX) $(LDFLAGS) -pthread $< $(OBJDIR)/affinity.o $(RXA) -o $@ @@ -109,7 +111,6 @@ $(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 diff --git a/src/affinity.cpp b/src/tests/affinity.cpp similarity index 93% rename from src/affinity.cpp rename to src/tests/affinity.cpp index fc05c29e..a73fcbd2 100644 --- a/src/affinity.cpp +++ b/src/tests/affinity.cpp @@ -1,5 +1,6 @@ /* Copyright (c) 2019, jtgrassie +Copyright (c) 2019, tevador All rights reserved. @@ -26,6 +27,8 @@ 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. */ +#include + #if defined(_WIN32) || defined(__CYGWIN__) #include #else @@ -95,20 +98,20 @@ cpuid_from_mask(uint64_t mask, const unsigned &thread_index) std::string mask_to_string(uint64_t mask) { - std::string r(65, '\0'); + std::ostringstream ss; 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'; + if (1ULL & v) + { + if (len == 0) len = i + 1; + ss << '1'; + } + else + if (len > 0) ss << '0'; } - return r; + return ss.str(); } diff --git a/src/affinity.hpp b/src/tests/affinity.hpp similarity index 100% rename from src/affinity.hpp rename to src/tests/affinity.hpp diff --git a/src/tests/benchmark.cpp b/src/tests/benchmark.cpp index 5582691f..9dba1c30 100644 --- a/src/tests/benchmark.cpp +++ b/src/tests/benchmark.cpp @@ -38,7 +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" +#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, diff --git a/vcxproj/benchmark.vcxproj b/vcxproj/benchmark.vcxproj index 165f100d..94835e13 100644 --- a/vcxproj/benchmark.vcxproj +++ b/vcxproj/benchmark.vcxproj @@ -115,6 +115,7 @@ + diff --git a/vcxproj/benchmark.vcxproj.filters b/vcxproj/benchmark.vcxproj.filters index 7c2339cb..ea182de5 100644 --- a/vcxproj/benchmark.vcxproj.filters +++ b/vcxproj/benchmark.vcxproj.filters @@ -18,6 +18,9 @@ Source Files + + Source Files +