diff --git a/CMakeLists.txt b/CMakeLists.txt index 8be1adcf..e58f6107 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,7 @@ set(HEADERS src/net/strategies/DonateStrategy.h src/Summary.h src/version.h + src/workers/Benchmark.h src/workers/Handle.h src/workers/Hashrate.h src/workers/OclThread.h @@ -120,6 +121,7 @@ set(SOURCES src/net/Network.cpp src/net/strategies/DonateStrategy.cpp src/Summary.cpp + src/workers/Benchmark.cpp src/workers/Handle.cpp src/workers/Hashrate.cpp src/workers/OclThread.cpp diff --git a/build.bat b/build.bat new file mode 100644 index 00000000..10d7c16b --- /dev/null +++ b/build.bat @@ -0,0 +1,18 @@ +@echo off +call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" +rmdir /S /Q build +del %~dp0\xmrig-amd-%1-win64.zip +mkdir build &&^ +cd build &&^ +git clone https://github.com/MoneroOcean/xmrig-amd.git &&^ +git clone https://github.com/xmrig/xmrig-deps.git &&^ +mkdir xmrig-amd\build &&^ +cd xmrig-amd\build &&^ +git checkout %1 &&^ +cmake .. -G "Visual Studio 15 2017 Win64" -DXMRIG_DEPS=%~dp0\build\xmrig-deps\msvc2017\x64 &&^ +msbuild /p:Configuration=Release xmrig-amd.sln &&^ +cd Release &&^ +copy ..\..\src\config.json . &&^ +7za a -tzip -mx %~dp0\xmrig-amd-%1-win64.zip xmrig-amd.exe config.json &&^ +cd %~dp0 &&^ +rmdir /S /Q build diff --git a/src/App.cpp b/src/App.cpp index c6de81c8..c862d38a 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,6 +40,7 @@ #include "Summary.h" #include "version.h" #include "workers/Workers.h" +#include "workers/Benchmark.h" #ifndef XMRIG_NO_HTTPD @@ -83,6 +85,8 @@ App::~App() # endif } +// this should be global since we register onJobResult using this object method +static Benchmark benchmark; int App::exec() { @@ -128,7 +132,26 @@ int App::exec() return 1; } - m_controller->network()->connect(); + // save config here to have option to store automatically generated "threads" + if (m_controller->config()->isShouldSave()) m_controller->config()->save(); + + // run benchmark before pool mining or not? + if (m_controller->config()->get_algo_perf(xmrig::PA_CN) == 0.0f || m_controller->config()->isCalibrateAlgo()) { + benchmark.set_controller(m_controller); // we need controller there to access config and network objects + benchmark.set_original_algorithm(m_controller->config()->algorithm()); + Workers::setListener(&benchmark); // register benchmark as job reault listener to compute hashrates there + // write text before first benchmark round + Log::i()->text(m_controller->config()->isColors() + ? GREEN_BOLD(" >>>>> ") WHITE_BOLD("STARTING ALGO PERFORMANCE CALIBRATION (with %i seconds round)") + : " >>>>> STARTING ALGO PERFORMANCE CALIBRATION (with %i seconds round)", + m_controller->config()->calibrateAlgoTime() + ); + // start benchmarking from first PerfAlgo in the list + if (m_controller->config()->get_algo_perf(xmrig::PA_CN) == 0.0f) benchmark.should_save_config(); + benchmark.start_perf_bench(xmrig::PerfAlgo::PA_CN); + } else { + m_controller->network()->connect(); + } const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); uv_loop_close(uv_default_loop()); diff --git a/src/amd/GpuContext.h b/src/amd/GpuContext.h index 733ca238..fa7fb2ee 100644 --- a/src/amd/GpuContext.h +++ b/src/amd/GpuContext.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +26,7 @@ #define __GPUCONTEXT_H__ -#include "3rdparty/CL/cl.h" +#include "amd/OclLib.h" #include @@ -73,6 +74,18 @@ struct GpuContext Nonce(0) {} + void release() { // stops all opencl kernels and releases all opencl resources + if (CommandQueues) { + OclLib::finish(CommandQueues); + OclLib::releaseCommandQueue(CommandQueues); + } + if (InputBuffer) OclLib::releaseMemObject(InputBuffer); + if (OutputBuffer) OclLib::releaseMemObject(OutputBuffer); + for (int i = 0; i < 6; ++ i) if (ExtraBuffers[i]) OclLib::releaseMemObject(ExtraBuffers[i]); + for (int i = 0; i < 11; ++ i) if (Kernels[i]) OclLib::releaseKernel(Kernels[i]); + if (Program) OclLib::releaseProgram(Program); + } + /*Input vars*/ size_t deviceIdx; size_t rawIntensity; diff --git a/src/amd/OclCLI.cpp b/src/amd/OclCLI.cpp index 6206097b..196cc67b 100644 --- a/src/amd/OclCLI.cpp +++ b/src/amd/OclCLI.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -56,7 +57,7 @@ bool OclCLI::setup(std::vector &threads) } -void OclCLI::autoConf(std::vector &threads, int *platformIndex, xmrig::Config *config) +void OclCLI::autoConf(std::vector &threads, int *platformIndex, const xmrig::Algorithm& algorithm, xmrig::Config *config) { *platformIndex = getAMDPlatformIdx(config); if (*platformIndex == -1) { @@ -71,7 +72,7 @@ void OclCLI::autoConf(std::vector &threads, int *platformIndex } constexpr size_t byteToMiB = 1024u * 1024u; - const size_t hashMemSize = xmrig::cn_select_memory(config->algorithm().algo()); + const size_t hashMemSize = xmrig::cn_select_memory(algorithm.algo()); for (GpuContext &ctx : devices) { // Vega APU slow and can cause BSOD, skip from autoconfig. @@ -96,7 +97,7 @@ void OclCLI::autoConf(std::vector &threads, int *platformIndex maxThreads = 2024u; } - if (config->algorithm().algo() == xmrig::CRYPTONIGHT_LITE) { + if (algorithm.algo() == xmrig::CRYPTONIGHT_LITE) { maxThreads *= 2u; } diff --git a/src/amd/OclCLI.h b/src/amd/OclCLI.h index 686db6f6..4c897257 100644 --- a/src/amd/OclCLI.h +++ b/src/amd/OclCLI.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +30,7 @@ #include "common/xmrig.h" +#include "common/crypto/Algorithm.h" // need it for new xmrig::Algorithm autoConf param class OclThread; @@ -46,7 +48,8 @@ class OclCLI OclCLI(); bool setup(std::vector &threads); - void autoConf(std::vector &threads, int *platformIndex, xmrig::Config *config); + // autoConf now takes Algorithm parameter as input + void autoConf(std::vector &threads, int *platformIndex, const xmrig::Algorithm&, xmrig::Config *config); void parseLaunch(const char *arg); inline void parseAffinity(const char *arg) { parse(m_affinity, arg); } diff --git a/src/amd/OclGPU.cpp b/src/amd/OclGPU.cpp index 03b056b2..9db52fd8 100644 --- a/src/amd/OclGPU.cpp +++ b/src/amd/OclGPU.cpp @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -402,7 +403,7 @@ size_t InitOpenCL(GpuContext* ctx, size_t num_gpus, xmrig::Config *config) # ifdef __GNUC__ cl_device_id TempDeviceList[num_gpus]; # else - cl_device_id* TempDeviceList = (cl_device_id*)_alloca(entries * sizeof(cl_device_id)); + cl_device_id* TempDeviceList = (cl_device_id*)_alloca(num_gpus * sizeof(cl_device_id)); # endif for (size_t i = 0; i < num_gpus; ++i) { @@ -410,7 +411,10 @@ size_t InitOpenCL(GpuContext* ctx, size_t num_gpus, xmrig::Config *config) TempDeviceList[i] = DeviceIDList[ctx[i].deviceIdx]; } - cl_context opencl_ctx = OclLib::createContext(nullptr, num_gpus, TempDeviceList, nullptr, nullptr, &ret); + // we store previous OpenCL context in static variable to be able to release it next time we do algo switch + static cl_context opencl_ctx = nullptr; + if (opencl_ctx) OclLib::releaseContext(opencl_ctx); + opencl_ctx = OclLib::createContext(nullptr, num_gpus, TempDeviceList, nullptr, nullptr, &ret); if(ret != CL_SUCCESS) { return OCL_ERR_API; } diff --git a/src/amd/OclLib.cpp b/src/amd/OclLib.cpp index bcf183c1..a97c73e6 100644 --- a/src/amd/OclLib.cpp +++ b/src/amd/OclLib.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -53,6 +54,11 @@ static const char *kGetPlatformInfo = "clGetPlatformInfo"; static const char *kGetProgramBuildInfo = "clGetProgramBuildInfo"; static const char *kGetProgramInfo = "clGetProgramInfo"; static const char *kSetKernelArg = "clSetKernelArg"; +static const char *kReleaseContext = "clReleaseContext"; +static const char *kReleaseProgram = "clReleaseProgram"; +static const char *kReleaseCommandQueue = "clReleaseCommandQueue"; +static const char *kReleaseMemObject = "clReleaseMemObject"; +static const char *kReleaseKernel = "clReleaseKernel"; typedef cl_command_queue (CL_API_CALL *createCommandQueueWithProperties_t)(cl_context, cl_device_id, const cl_queue_properties *, cl_int *); typedef cl_command_queue (CL_API_CALL *createCommandQueue_t)(cl_context, cl_device_id, cl_command_queue_properties, cl_int *); @@ -73,6 +79,11 @@ typedef cl_kernel (CL_API_CALL *createKernel_t)(cl_program, const char *, cl_int typedef cl_mem (CL_API_CALL *createBuffer_t)(cl_context, cl_mem_flags, size_t, void *, cl_int *); typedef cl_program (CL_API_CALL *createProgramWithBinary_t)(cl_context, cl_uint, const cl_device_id *, const size_t *, const unsigned char **, cl_int *, cl_int *); typedef cl_program (CL_API_CALL *createProgramWithSource_t)(cl_context, cl_uint, const char **, const size_t *, cl_int *); +typedef cl_int (CL_API_CALL *releaseContext_t)(cl_context); +typedef cl_int (CL_API_CALL *releaseProgram_t)(cl_program); +typedef cl_int (CL_API_CALL *releaseCommandQueue_t)(cl_command_queue); +typedef cl_int (CL_API_CALL *releaseMemObject_t)(cl_mem); +typedef cl_int (CL_API_CALL *releaseKernel_t)(cl_kernel); static createCommandQueueWithProperties_t pCreateCommandQueueWithProperties = nullptr; static createCommandQueue_t pCreateCommandQueue = nullptr; @@ -93,6 +104,11 @@ static createKernel_t pCreateKernel = nu static createBuffer_t pCreateBuffer = nullptr; static createProgramWithBinary_t pCreateProgramWithBinary = nullptr; static createProgramWithSource_t pCreateProgramWithSource = nullptr; +static releaseContext_t pReleaseContext = nullptr; +static releaseProgram_t pReleaseProgram = nullptr; +static releaseCommandQueue_t pReleaseCommandQueue = nullptr; +static releaseMemObject_t pReleaseMemObject = nullptr; +static releaseKernel_t pReleaseKernel = nullptr; #define DLSYM(x) if (uv_dlsym(&oclLib, k##x, reinterpret_cast(&p##x)) == -1) { return false; } @@ -128,6 +144,11 @@ bool OclLib::load() DLSYM(CreateBuffer); DLSYM(CreateProgramWithBinary); DLSYM(CreateProgramWithSource); + DLSYM(ReleaseContext); + DLSYM(ReleaseProgram); + DLSYM(ReleaseCommandQueue); + DLSYM(ReleaseMemObject); + DLSYM(ReleaseKernel); uv_dlsym(&oclLib, kCreateCommandQueueWithProperties, reinterpret_cast(&pCreateCommandQueueWithProperties)); @@ -335,3 +356,42 @@ cl_program OclLib::createProgramWithSource(cl_context context, cl_uint count, co return result; } + +cl_int OclLib::releaseContext(cl_context context) +{ + assert(pReleaseContext != nullptr); + + return pReleaseContext(context); +} + + +cl_int OclLib::releaseProgram(cl_program program) +{ + assert(pReleaseProgram != nullptr); + + return pReleaseProgram(program); +} + + +cl_int OclLib::releaseCommandQueue(cl_command_queue command_queue) +{ + assert(pReleaseCommandQueue != nullptr); + + return pReleaseCommandQueue(command_queue); +} + + +cl_int OclLib::releaseMemObject(cl_mem memobj) +{ + assert(pReleaseMemObject != nullptr); + + return pReleaseMemObject(memobj); +} + + +cl_int OclLib::releaseKernel(cl_kernel kernel) +{ + assert(pReleaseKernel != nullptr); + + return pReleaseKernel(kernel); +} \ No newline at end of file diff --git a/src/amd/OclLib.h b/src/amd/OclLib.h index 987859a2..a96c36e2 100644 --- a/src/amd/OclLib.h +++ b/src/amd/OclLib.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,6 +52,12 @@ class OclLib static cl_mem createBuffer(cl_context context, cl_mem_flags flags, size_t size, void *host_ptr, cl_int *errcode_ret); static cl_program createProgramWithBinary(cl_context context, cl_uint num_devices, const cl_device_id *device_list, const size_t *lengths, const unsigned char **binaries, cl_int *binary_status, cl_int *errcode_ret); static cl_program createProgramWithSource(cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret); + // we need to properly release OpenCL we created to be able to do algo switching + static cl_int releaseContext(cl_context context); + static cl_int releaseProgram(cl_program program); + static cl_int releaseCommandQueue(cl_command_queue command_queue); + static cl_int releaseMemObject(cl_mem memobj); + static cl_int releaseKernel(cl_kernel kernel); private: static bool load(); diff --git a/src/amd/opencl/cryptonight.cl b/src/amd/opencl/cryptonight.cl index 16413d9f..8a79ccff 100644 --- a/src/amd/opencl/cryptonight.cl +++ b/src/amd/opencl/cryptonight.cl @@ -468,9 +468,11 @@ __kernel void cn0(__global ulong *input, __global uint4 *Scratchpad, __global ul mem_fence(CLK_LOCAL_MEM_FENCE); # if (ALGO == CRYPTONIGHT_HEAVY) - { - __local uint4 xin[8][WORKSIZE]; + __local uint4 xin[8][WORKSIZE]; +# endif +# if (ALGO == CRYPTONIGHT_HEAVY) + { /* Also left over threads perform this loop. * The left over thread results will be ignored */ diff --git a/src/common/config/CommonConfig.cpp b/src/common/config/CommonConfig.cpp index 7e43b39d..49c17055 100644 --- a/src/common/config/CommonConfig.cpp +++ b/src/common/config/CommonConfig.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,6 +46,8 @@ xmrig::CommonConfig::CommonConfig() : m_background(false), m_colors(true), m_dryRun(false), + m_calibrateAlgo(false), + m_calibrateAlgoTime(60), m_syslog(false), # ifdef XMRIG_PROXY_PROJECT @@ -183,6 +186,10 @@ bool xmrig::CommonConfig::parseBoolean(int key, bool enable) m_dryRun = enable; break; + case IConfig::CalibrateAlgoKey: /* --calibrate-algo */ + m_calibrateAlgo = enable; + break; + default: break; } @@ -267,6 +274,7 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg) case NicehashKey: /* --nicehash */ case ApiIPv6Key: /* --api-ipv6 */ case DryRunKey: /* --dry-run */ + case CalibrateAlgoKey: /* --calibrate-algo */ return parseBoolean(key, true); case ColorKey: /* --no-color */ @@ -283,6 +291,9 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg) # endif return parseUint64(key, strtol(arg, nullptr, 10)); + case CalibrateAlgoTimeKey: /* --calibrate-algo-time */ + return parseUint64(key, strtol(arg, nullptr, 10)); + default: break; } @@ -344,6 +355,12 @@ bool xmrig::CommonConfig::parseInt(int key, int arg) } break; + case CalibrateAlgoTimeKey: /* --calibrate-algo-time */ + if (arg >= 5 && arg <= 3600) { + m_calibrateAlgoTime = arg; + } + break; + default: break; } diff --git a/src/common/config/CommonConfig.h b/src/common/config/CommonConfig.h index ffebb6b2..c048d337 100644 --- a/src/common/config/CommonConfig.h +++ b/src/common/config/CommonConfig.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -48,6 +49,8 @@ class CommonConfig : public IConfig inline bool isBackground() const { return m_background; } inline bool isColors() const { return m_colors; } inline bool isDryRun() const { return m_dryRun; } + inline bool isCalibrateAlgo() const { return m_calibrateAlgo; } + inline int calibrateAlgoTime() const { return m_calibrateAlgoTime; } inline bool isSyslog() const { return m_syslog; } inline const char *apiToken() const { return m_apiToken.data(); } inline const char *apiWorkerId() const { return m_apiWorkerId.data(); } @@ -63,6 +66,7 @@ class CommonConfig : public IConfig inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); } inline const Algorithm &algorithm() const override { return m_algorithm; } + inline void set_algorithm(const Algorithm& algorithm) { m_algorithm = algorithm; } inline const char *fileName() const override { return m_fileName.data(); } bool save() override; @@ -87,6 +91,8 @@ class CommonConfig : public IConfig bool m_background; bool m_colors; bool m_dryRun; + bool m_calibrateAlgo; + int m_calibrateAlgoTime; bool m_syslog; bool m_watch; int m_apiPort; diff --git a/src/common/crypto/Algorithm.cpp b/src/common/crypto/Algorithm.cpp index 31035fb1..c253d9c8 100644 --- a/src/common/crypto/Algorithm.cpp +++ b/src/common/crypto/Algorithm.cpp @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -223,3 +224,51 @@ const char *xmrig::Algorithm::name(bool shortName) const return "invalid"; } + + +// returns string name of the PerfAlgo +const char *xmrig::Algorithm::perfAlgoName(const xmrig::PerfAlgo pa) { + static const char* perf_algo_names[xmrig::PerfAlgo::PA_MAX] = { + "cn", + "cn-fast", + "cn-lite", + "cn-heavy", + }; + return perf_algo_names[pa]; +} + +// constructs Algorithm from PerfAlgo +xmrig::Algorithm::Algorithm(const xmrig::PerfAlgo pa) { + switch (pa) { + case PA_CN: + m_algo = xmrig::CRYPTONIGHT; + m_variant = xmrig::VARIANT_1; + break; + case PA_CN_FAST: + m_algo = xmrig::CRYPTONIGHT; + m_variant = xmrig::VARIANT_MSR; + break; + case PA_CN_LITE: + m_algo = xmrig::CRYPTONIGHT_LITE; + m_variant = xmrig::VARIANT_1; + break; + case PA_CN_HEAVY: + m_algo = xmrig::CRYPTONIGHT_HEAVY; + m_variant = xmrig::VARIANT_0; + break; + default: + m_algo = xmrig::INVALID_ALGO; + m_variant = xmrig::VARIANT_AUTO; + } +} + +// returns PerfAlgo that corresponds to current Algorithm +xmrig::PerfAlgo xmrig::Algorithm::perf_algo() const { + if (m_variant == VARIANT_MSR) return PA_CN_FAST; + switch (m_algo) { + case CRYPTONIGHT: return PA_CN; + case CRYPTONIGHT_LITE: return PA_CN_LITE; + case CRYPTONIGHT_HEAVY: return PA_CN_HEAVY; + default: return PA_INVALID; + } +} diff --git a/src/common/crypto/Algorithm.h b/src/common/crypto/Algorithm.h index bcf029d8..bb8c5220 100644 --- a/src/common/crypto/Algorithm.h +++ b/src/common/crypto/Algorithm.h @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -43,12 +44,15 @@ class Algorithm m_variant(VARIANT_AUTO) {} - inline Algorithm(Algo algo, Variant variant) : + inline Algorithm(Algo algo, Variant variant = VARIANT_AUTO) : m_variant(variant) { setAlgo(algo); } + // constructs Algorithm from PerfAlgo + Algorithm(const xmrig::PerfAlgo); + inline Algorithm(const char *algo) { parseAlgorithm(algo); @@ -56,8 +60,10 @@ class Algorithm bool isEqual(const Algorithm &other) const { return m_algo == other.m_algo && m_variant == other.m_variant; } inline Algo algo() const { return m_algo; } + xmrig::PerfAlgo perf_algo() const; // returns PerfAlgo that corresponds to current Algorithm inline const char *name() const { return name(false); } inline const char *shortName() const { return name(true); } + static const char *perfAlgoName(xmrig::PerfAlgo); // returns string name of the PerfAlgo inline Variant variant() const { return m_variant; } inline void setVariant(Variant variant) { m_variant = variant; } diff --git a/src/common/interfaces/IConfig.h b/src/common/interfaces/IConfig.h index 4b3f8788..db480ca9 100644 --- a/src/common/interfaces/IConfig.h +++ b/src/common/interfaces/IConfig.h @@ -5,6 +5,7 @@ * Copyright 2014-2016 Wolf9466 * Copyright 2016 Jay D Dee * Copyright 2016-2018 XMRig + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -67,6 +68,8 @@ class IConfig CPUPriorityKey = 1021, NicehashKey = 1006, PrintTimeKey = 1007, + CalibrateAlgoKey = 10001, + CalibrateAlgoTimeKey = 10002, // xmrig cpu AVKey = 'v', diff --git a/src/common/net/Client.cpp b/src/common/net/Client.cpp index f4553d97..8ca39775 100644 --- a/src/common/net/Client.cpp +++ b/src/common/net/Client.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +34,8 @@ #include "common/log/Log.h" #include "common/net/Client.h" #include "net/JobResult.h" +#include "core/Config.h" // for pconfig to access pconfig->get_algo_perf +#include "workers/Workers.h" // to do Workers::switch_algo #include "rapidjson/document.h" #include "rapidjson/error/en.h" #include "rapidjson/stringbuffer.h" @@ -269,10 +272,6 @@ bool Client::parseJob(const rapidjson::Value ¶ms, int *code) return false; } - if (params.HasMember("algo")) { - job.algorithm().parseAlgorithm(params["algo"].GetString()); - } - if (params.HasMember("variant")) { const rapidjson::Value &variant = params["variant"]; @@ -284,6 +283,11 @@ bool Client::parseJob(const rapidjson::Value ¶ms, int *code) } } + // moved algo after variant parsing to override variant that is considered to be outdated now + if (params.HasMember("algo")) { + job.algorithm().parseAlgorithm(params["algo"].GetString()); + } + if (!verifyAlgorithm(job.algorithm())) { *code = 6; @@ -291,6 +295,9 @@ bool Client::parseJob(const rapidjson::Value ¶ms, int *code) return false; } + // retarget workers for possible new Algo profile (same algo profile is not reapplied) + Workers::switch_algo(job.algorithm()); + if (m_job != job) { m_jobs++; m_job = std::move(job); @@ -495,6 +502,16 @@ void Client::login() } params.AddMember("algo", algo, allocator); + + // addding algo-perf based on pconfig->get_algo_perf + Value algo_perf(kObjectType); + for (int a = 0; a != xmrig::PerfAlgo::PA_MAX; ++ a) { + const xmrig::PerfAlgo pa = static_cast(a); + Value key(xmrig::Algorithm::perfAlgoName(pa), allocator); + algo_perf.AddMember(key, Value(xmrig::pconfig->get_algo_perf(pa)), allocator); + } + + params.AddMember("algo-perf", algo_perf, allocator); } doc.AddMember("params", params, allocator); diff --git a/src/common/net/Client.h b/src/common/net/Client.h index 4be8badb..f98efe1f 100644 --- a/src/common/net/Client.h +++ b/src/common/net/Client.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -74,7 +75,6 @@ class Client inline int id() const { return m_id; } inline SocketState state() const { return m_state; } inline uint16_t port() const { return m_pool.port(); } - inline void setAlgo(const xmrig::Algorithm &algo) { m_pool.setAlgo(algo); } inline void setQuiet(bool quiet) { m_quiet = quiet; } inline void setRetries(int retries) { m_retries = retries; } inline void setRetryPause(int ms) { m_retryPause = ms; } diff --git a/src/common/net/Job.cpp b/src/common/net/Job.cpp index 80b521ea..2e7204fb 100644 --- a/src/common/net/Job.cpp +++ b/src/common/net/Job.cpp @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -120,6 +121,12 @@ bool Job::setBlob(const char *blob) return true; } +// for algo benchmarking +void Job::setRawBlob(const uint8_t *blob, const size_t size) +{ + memcpy(m_blob, blob, m_size = size); +} + bool Job::setTarget(const char *target) { diff --git a/src/common/net/Job.h b/src/common/net/Job.h index 049eb7d4..050bff48 100644 --- a/src/common/net/Job.h +++ b/src/common/net/Job.h @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,7 +43,10 @@ class Job ~Job(); bool setBlob(const char *blob); + void setRawBlob(const uint8_t *blob, const size_t size); // for algo benchmarking bool setTarget(const char *target); + // for algo benchmarking to set PoW variant + void setAlgorithm(const xmrig::Algorithm& algorithm) { m_algorithm = algorithm; } xmrig::Variant variant() const; inline bool isNicehash() const { return m_nicehash; } diff --git a/src/common/net/Pool.cpp b/src/common/net/Pool.cpp index 053f2507..26a0468e 100644 --- a/src/common/net/Pool.cpp +++ b/src/common/net/Pool.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -48,6 +49,20 @@ Pool::Pool() : m_keepAlive(0), m_port(kDefaultPort) { + // here xmrig now resuts all possible supported algorithms + m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT, xmrig::VARIANT_1)); + m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT, xmrig::VARIANT_0)); + m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT, xmrig::VARIANT_XTL)); + m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT, xmrig::VARIANT_MSR)); + m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT, xmrig::VARIANT_XAO)); + m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT, xmrig::VARIANT_RTO)); + + m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_1)); + m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT_LITE, xmrig::VARIANT_0)); + + m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_0)); + m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_XHV)); + m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_TUBE)); } @@ -233,16 +248,6 @@ void Pool::adjust(const xmrig::Algorithm &algorithm) m_algorithm.setAlgo(algorithm.algo()); adjustVariant(algorithm.variant()); } - - rebuild(); -} - - -void Pool::setAlgo(const xmrig::Algorithm &algorithm) -{ - m_algorithm = algorithm; - - rebuild(); } @@ -285,17 +290,6 @@ bool Pool::parseIPv6(const char *addr) } -void Pool::addVariant(xmrig::Variant variant) -{ - const xmrig::Algorithm algorithm(m_algorithm.algo(), variant); - if (!algorithm.isValid() || m_algorithm == algorithm) { - return; - } - - m_algorithms.push_back(algorithm); -} - - void Pool::adjustVariant(const xmrig::Variant variantHint) { # ifndef XMRIG_PROXY_PROJECT @@ -364,27 +358,3 @@ void Pool::adjustVariant(const xmrig::Variant variantHint) } # endif } - - -void Pool::rebuild() -{ - m_algorithms.clear(); - - if (!m_algorithm.isValid()) { - return; - } - - m_algorithms.push_back(m_algorithm); - -# ifndef XMRIG_PROXY_PROJECT - addVariant(xmrig::VARIANT_1); - addVariant(xmrig::VARIANT_0); - addVariant(xmrig::VARIANT_XTL); - addVariant(xmrig::VARIANT_TUBE); - addVariant(xmrig::VARIANT_MSR); - addVariant(xmrig::VARIANT_XHV); - addVariant(xmrig::VARIANT_XAO); - addVariant(xmrig::VARIANT_RTO); - addVariant(xmrig::VARIANT_AUTO); -# endif -} diff --git a/src/common/net/Pool.h b/src/common/net/Pool.h index 57a30d1e..04a26818 100644 --- a/src/common/net/Pool.h +++ b/src/common/net/Pool.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -78,7 +79,6 @@ class Pool bool setUserpass(const char *userpass); rapidjson::Value toJSON(rapidjson::Document &doc) const; void adjust(const xmrig::Algorithm &algorithm); - void setAlgo(const xmrig::Algorithm &algorithm); # ifdef APP_DEBUG void print() const; @@ -86,9 +86,7 @@ class Pool private: bool parseIPv6(const char *addr); - void addVariant(xmrig::Variant variant); void adjustVariant(const xmrig::Variant variantHint); - void rebuild(); bool m_nicehash; int m_keepAlive; diff --git a/src/common/xmrig.h b/src/common/xmrig.h index 58a3540c..b7c9d0dd 100644 --- a/src/common/xmrig.h +++ b/src/common/xmrig.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,9 +34,19 @@ enum Algo { INVALID_ALGO = -1, CRYPTONIGHT, /* CryptoNight (Monero) */ CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */ - CRYPTONIGHT_HEAVY /* CryptoNight-Heavy (RYO) */ + CRYPTONIGHT_HEAVY, /* CryptoNight-Heavy (RYO) */ + ALGO_MAX }; +// algorithms that can has different performance +enum PerfAlgo { + PA_INVALID = -1, + PA_CN, /* CryptoNight (Monero) */ + PA_CN_FAST, /* CryptoNight-Fast (Masari) */ + PA_CN_LITE, /* CryptoNight-Lite (AEON) */ + PA_CN_HEAVY, /* CryptoNight-Heavy (RYO) */ + PA_MAX +}; //--av=1 For CPUs with hardware AES. //--av=2 Lower power mode (double hash) of 1. diff --git a/src/config.json b/src/config.json index 45d4759e..bb6d2180 100644 --- a/src/config.json +++ b/src/config.json @@ -27,6 +27,9 @@ "retries": 5, "retry-pause": 5, "threads": null, + "algo-perf": null, + "calibrate-algo": false, + "calibrate-algo-time": 60, "user-agent": null, "syslog": false, "watch": false diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 874acd7d..1b0c152e 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,6 +41,12 @@ #include "workers/OclThread.h" +// for usage in Client::login to get_algo_perf +namespace xmrig { + Config* pconfig = nullptr; +}; + + xmrig::Config::Config() : xmrig::CommonConfig(), m_autoConf(false), m_cache(true), @@ -51,6 +58,11 @@ xmrig::Config::Config() : xmrig::CommonConfig(), m_loader("libOpenCL.so") # endif { + // not defined algo performance is considered to be 0 + for (int a = 0; a != xmrig::PerfAlgo::PA_MAX; ++ a) { + const xmrig::PerfAlgo pa = static_cast(a); + m_algo_perf[pa] = 0.0f; + } } @@ -63,10 +75,13 @@ bool xmrig::Config::oclInit() { LOG_WARN("compiling code and initializing GPUs. This will take a while..."); - if (m_threads.empty() && !m_oclCLI.setup(m_threads)) { - m_autoConf = true; - m_shouldSave = true; - m_oclCLI.autoConf(m_threads, &m_platformIndex, this); + for (int a = 0; a != xmrig::Algo::ALGO_MAX; ++ a) { + const xmrig::Algo algo = static_cast(a); + if (m_threads[algo].empty() && !m_oclCLI.setup(m_threads[algo])) { + m_autoConf = true; + m_shouldSave = true; + m_oclCLI.autoConf(m_threads[algo], &m_platformIndex, xmrig::Algorithm(algo), this); + } } return true; @@ -116,12 +131,31 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const doc.AddMember("retries", retries(), allocator); doc.AddMember("retry-pause", retryPause(), allocator); - Value threads(kArrayType); - for (const IThread *thread : m_threads) { - threads.PushBack(thread->toConfig(doc), allocator); + // save extended "threads" based on m_threads + Value threads(kObjectType); + for (int a = 0; a != xmrig::Algo::ALGO_MAX; ++ a) { + const xmrig::Algo algo = static_cast(a); + Value key(xmrig::Algorithm::perfAlgoName(xmrig::Algorithm(algo).perf_algo()), allocator); + Value threads2(kArrayType); + for (const IThread *thread : m_threads[algo]) { + threads2.PushBack(thread->toConfig(doc), allocator); + } + threads.AddMember(key, threads2, allocator); } doc.AddMember("threads", threads, allocator); + // save "algo-perf" based on m_algo_perf + Value algo_perf(kObjectType); + for (int a = 0; a != xmrig::PerfAlgo::PA_MAX; ++ a) { + const xmrig::PerfAlgo pa = static_cast(a); + Value key(xmrig::Algorithm::perfAlgoName(pa), allocator); + algo_perf.AddMember(key, Value(m_algo_perf[pa]), allocator); + } + doc.AddMember("algo-perf", algo_perf, allocator); + + doc.AddMember("calibrate-algo", isCalibrateAlgo(), allocator); + doc.AddMember("calibrate-algo-time", calibrateAlgoTime(), allocator); + doc.AddMember("user-agent", userAgent() ? Value(StringRef(userAgent())).Move() : Value(kNullType).Move(), allocator); doc.AddMember("syslog", isSyslog(), allocator); doc.AddMember("watch", m_watch, allocator); @@ -228,26 +262,54 @@ bool xmrig::Config::parseUint64(int key, uint64_t arg) return true; } +// parse specific perf algo (or generic) threads config +void xmrig::Config::parseThreadsJSON(const rapidjson::Value &threads, const xmrig::Algo algo) +{ + for (const rapidjson::Value &value : threads.GetArray()) { + if (!value.IsObject()) { + continue; + } + + if (value.HasMember("intensity")) { + parseThread(value, algo); + } + } +} void xmrig::Config::parseJSON(const rapidjson::Document &doc) { const rapidjson::Value &threads = doc["threads"]; if (threads.IsArray()) { - for (const rapidjson::Value &value : threads.GetArray()) { - if (!value.IsObject()) { - continue; + // parse generic (old) threads + parseThreadsJSON(threads, m_algorithm.algo()); + } else if (threads.IsObject()) { + // parse new specific perf algo threads + for (int a = 0; a != xmrig::Algo::ALGO_MAX; ++ a) { + const xmrig::Algo algo = static_cast(a); + const rapidjson::Value &threads2 = threads[xmrig::Algorithm::perfAlgoName(xmrig::Algorithm(algo).perf_algo())]; + if (threads2.IsArray()) { + parseThreadsJSON(threads2, algo); } + } + } - if (value.HasMember("intensity")) { - parseThread(value); + const rapidjson::Value &algo_perf = doc["algo-perf"]; + if (algo_perf.IsObject()) { + for (int a = 0; a != xmrig::PerfAlgo::PA_MAX; ++ a) { + const xmrig::PerfAlgo pa = static_cast(a); + const rapidjson::Value &key = algo_perf[xmrig::Algorithm::perfAlgoName(pa)]; + if (key.IsDouble()) { + m_algo_perf[pa] = static_cast(key.GetDouble()); + } else if (key.IsInt()) { + m_algo_perf[pa] = static_cast(key.GetInt()); } } } } -void xmrig::Config::parseThread(const rapidjson::Value &object) +void xmrig::Config::parseThread(const rapidjson::Value &object, const xmrig::Algo algo) { - m_threads.push_back(new OclThread(object)); + m_threads[algo].push_back(new OclThread(object)); } diff --git a/src/core/Config.h b/src/core/Config.h index a7faea95..7a740b6e 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,9 +58,16 @@ class Config : public CommonConfig inline bool isOclCache() const { return m_cache; } inline bool isShouldSave() const { return m_shouldSave; } inline const char *loader() const { return m_loader.data(); } - inline const std::vector &threads() const { return m_threads; } + // access to m_threads taking into accoun that it is now separated for each perf algo + inline const std::vector &threads(const xmrig::Algo algo = INVALID_ALGO) const { + return m_threads[algo == INVALID_ALGO ? m_algorithm.algo() : algo]; + } inline int platformIndex() const { return m_platformIndex; } + // access to perf algo results + inline float get_algo_perf(const xmrig::PerfAlgo pa) const { return m_algo_perf[pa]; } + inline void set_algo_perf(const xmrig::PerfAlgo pa, const float value) { m_algo_perf[pa] = value; } + static Config *load(int argc, char **argv, IWatcherListener *listener); protected: @@ -68,19 +76,25 @@ class Config : public CommonConfig bool parseString(int key, const char *arg) override; bool parseUint64(int key, uint64_t arg) override; void parseJSON(const rapidjson::Document &doc) override; + // parse specific perf algo (or generic) threads config + void parseThreadsJSON(const rapidjson::Value &threads, xmrig::Algo); private: - void parseThread(const rapidjson::Value &object); + void parseThread(const rapidjson::Value &object, const xmrig::Algo); bool m_autoConf; bool m_cache; bool m_shouldSave; int m_platformIndex; OclCLI m_oclCLI; - std::vector m_threads; + // threads config for each perf algo + std::vector m_threads[xmrig::Algo::ALGO_MAX]; + // perf algo hashrate results + float m_algo_perf[xmrig::PerfAlgo::PA_MAX]; xmrig::c_str m_loader; }; +extern Config* pconfig; } /* namespace xmrig */ diff --git a/src/core/ConfigLoader_platform.h b/src/core/ConfigLoader_platform.h index da191cdb..4447429b 100644 --- a/src/core/ConfigLoader_platform.h +++ b/src/core/ConfigLoader_platform.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * * This program is free software: you can redistribute it and/or modify @@ -54,6 +55,8 @@ Options:\n\ cryptonight-heavy\n" #endif "\ + --calibrate-algo run benchmarks before mining to measure hashrates of all supported algos\n\ + --calibrate-algo-time=N time in seconds to run each algo benchmark round (default: 60)\n\ -o, --url=URL URL of mining server\n\ -O, --userpass=U:P username:password pair for mining server\n\ -u, --user=USERNAME username for mining server\n\ @@ -106,6 +109,8 @@ static struct option const options[] = { { "config", 1, nullptr, xmrig::IConfig::ConfigKey }, { "donate-level", 1, nullptr, xmrig::IConfig::DonateLevelKey }, { "dry-run", 0, nullptr, xmrig::IConfig::DryRunKey }, + { "calibrate-algo", 0, nullptr, xmrig::IConfig::CalibrateAlgoKey }, + { "calibrate-algo-time", 1, nullptr, xmrig::IConfig::CalibrateAlgoTimeKey }, { "help", 0, nullptr, xmrig::IConfig::HelpKey }, { "keepalive", 0, nullptr, xmrig::IConfig::KeepAliveKey }, { "log-file", 1, nullptr, xmrig::IConfig::LogFileKey }, @@ -140,6 +145,8 @@ static struct option const config_options[] = { { "colors", 0, nullptr, xmrig::IConfig::ColorKey }, { "donate-level", 1, nullptr, xmrig::IConfig::DonateLevelKey }, { "dry-run", 0, nullptr, xmrig::IConfig::DryRunKey }, + { "calibrate-algo", 0, nullptr, xmrig::IConfig::CalibrateAlgoKey }, + { "calibrate-algo-time", 1, nullptr, xmrig::IConfig::CalibrateAlgoTimeKey }, { "log-file", 1, nullptr, xmrig::IConfig::LogFileKey }, { "print-time", 1, nullptr, xmrig::IConfig::PrintTimeKey }, { "retries", 1, nullptr, xmrig::IConfig::RetriesKey }, diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index 5f11f05c..bc667a2c 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -103,7 +104,8 @@ int xmrig::Controller::init(int argc, char **argv) { Cpu::init(); - d_ptr->config = xmrig::Config::load(argc, argv, this); + // init pconfig global pointer to config + pconfig = d_ptr->config = xmrig::Config::load(argc, argv, this); if (!d_ptr->config) { return 1; } diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp index 6e02e8fa..ef21015b 100644 --- a/src/crypto/CryptoNight.cpp +++ b/src/crypto/CryptoNight.cpp @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -152,6 +153,7 @@ CryptoNight::cn_hash_fun CryptoNight::fn(xmrig::Algo algorithm, xmrig::AlgoVerif cryptonight_ctx *CryptoNight::createCtx(xmrig::Algo algorithm) { + m_algorithm = algorithm; // register algo switch in m_algorithm after its context creation cryptonight_ctx *ctx = static_cast(_mm_malloc(sizeof(cryptonight_ctx), 16)); ctx->memory = static_cast(_mm_malloc(xmrig::cn_select_memory(algorithm), 16)); diff --git a/src/workers/Benchmark.cpp b/src/workers/Benchmark.cpp new file mode 100644 index 00000000..b164df39 --- /dev/null +++ b/src/workers/Benchmark.cpp @@ -0,0 +1,93 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "workers/Benchmark.h" +#include "workers/Workers.h" +#include "core/Config.h" +#include "net/Network.h" +#include "common/log/Log.h" +#include + +// start performance measurements for specified perf algo +void Benchmark::start_perf_bench(const xmrig::PerfAlgo pa) { + Workers::switch_algo(xmrig::Algorithm(pa)); // switch workers to new algo (Algo part) + + // prepare test job for benchmark runs + Job job; + job.setPoolId(-100); // to make sure we can detect benchmark jobs + job.setId(xmrig::Algorithm::perfAlgoName(pa)); // need to set different id so that workers will see job change + const static uint8_t test_input[76] = { + 0x99, // 0x99 here to trigger all future algo versions for auto veriant detection based on block version + 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00, + 0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B, + 0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62, + 0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92, + 0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01, + }; + job.setRawBlob(test_input, 76); + job.setTarget("FFFFFFFFFFFFFF00"); // set difficulty to 256 cause onJobResult after every 256-th computed hash + job.setAlgorithm(xmrig::Algorithm(pa)); // set job algo (for Variant part) + m_pa = pa; // current perf algo + m_hash_count = 0; // number of hashes calculated for current perf algo + m_time_start = 0; // init time of measurements start (in ms) during the first onJobResult + Workers::setJob(job, false); // set job for workers to compute +} + +void Benchmark::onJobResult(const JobResult& result) { + if (result.poolId != -100) { // switch to network pool jobs + Workers::setListener(m_controller->network()); + static_cast(m_controller->network())->onJobResult(result); + return; + } + // ignore benchmark results for other perf algo + if (m_pa == xmrig::PA_INVALID || result.jobId != xmrig::Id(xmrig::Algorithm::perfAlgoName(m_pa))) return; + ++ m_hash_count; + const uint64_t now = get_now(); + if (!m_time_start) m_time_start = now; // time of measurements start (in ms) + else if (now - m_time_start > static_cast(m_controller->config()->calibrateAlgoTime())*1000) { // end of benchmark round for m_pa + const float hashrate = static_cast(m_hash_count) * result.diff / (now - m_time_start) * 1000.0f; + m_controller->config()->set_algo_perf(m_pa, hashrate); // store hashrate result + Log::i()->text(m_controller->config()->isColors() + ? GREEN_BOLD(" ===> ") CYAN_BOLD("%s") WHITE_BOLD(" hashrate: ") CYAN_BOLD("%f") + : " ===> %s hasrate: %f", + xmrig::Algorithm::perfAlgoName(m_pa), + hashrate + ); + const xmrig::PerfAlgo next_pa = static_cast(m_pa + 1); // compute next perf algo to benchmark + if (next_pa != xmrig::PerfAlgo::PA_MAX) { + start_perf_bench(next_pa); + } else { // end of benchmarks and switching to jobs from the pool (network) + m_pa = xmrig::PA_INVALID; + if (m_shouldSaveConfig) m_controller->config()->save(); // save config with measured algo-perf + Workers::pause(); // do not compute anything before job from the pool + Workers::switch_algo(m_algorithm_orig); // switch workers to the original algorithm + m_controller->network()->connect(); + } + } +} + +uint64_t Benchmark::get_now() const { // get current time in ms + using namespace std::chrono; + return time_point_cast(high_resolution_clock::now()).time_since_epoch().count(); +} diff --git a/src/workers/Benchmark.h b/src/workers/Benchmark.h new file mode 100644 index 00000000..2729616c --- /dev/null +++ b/src/workers/Benchmark.h @@ -0,0 +1,54 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +#include "common/xmrig.h" +#include "interfaces/IJobResultListener.h" +#include "core/Controller.h" +#include "common/crypto/Algorithm.h" + +class Benchmark : public IJobResultListener { + bool m_shouldSaveConfig; // should save config after all benchmark rounds + xmrig::PerfAlgo m_pa; // current perf algo we benchmark + uint64_t m_hash_count; // number of hashes calculated for current perf algo + uint64_t m_time_start; // time of measurements start for current perf algo (in ms) + xmrig::Controller* m_controller; // to get access to config and network + xmrig::Algorithm m_algorithm_orig; // previous algorithm to restore after benchmarking + + uint64_t get_now() const; // get current time in ms + + void onJobResult(const JobResult&) override; // onJobResult is called after each computed benchmark hash + + public: + Benchmark() : m_shouldSaveConfig(false) {} + virtual ~Benchmark() {} + + void set_controller(xmrig::Controller* controller) { m_controller = controller; } + void set_original_algorithm(const xmrig::Algorithm& algorithm) { m_algorithm_orig = algorithm; } + void should_save_config() { m_shouldSaveConfig = true; } + void start_perf_bench(const xmrig::PerfAlgo); // start benchmark for specified perf algo +}; diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 8ec04855..7d6990de 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -212,13 +213,80 @@ bool Workers::start(xmrig::Controller *controller) handle->start(Workers::onReady); } - if (controller->config()->isShouldSave()) { - controller->config()->save(); + return true; +} + +void Workers::soft_stop() // stop current workers leaving uv stuff intact (used in switch_algo) +{ + if (m_hashrate) { + m_hashrate->stop(); + delete m_hashrate; } - return true; + m_sequence = 0; + m_paused = 0; + + for (size_t i = 0; i < m_workers.size(); ++i) { + m_workers[i]->join(); + delete m_workers[i]; + } + m_workers.clear(); + + for (size_t i = 0; i < contexts.size(); ++i) contexts[i].release(); } +// setups workers based on specified algorithm (or its basic perf algo more specifically) +bool Workers::switch_algo(const xmrig::Algorithm& algorithm) +{ + if (m_controller->config()->algorithm().algo() == algorithm.algo()) return true; + + soft_stop(); + + m_sequence = 1; + m_paused = 1; + + const std::vector &threads = m_controller->config()->threads(algorithm.algo()); + m_controller->config()->set_algorithm(algorithm); + + Log::i()->text(m_controller->config()->isColors() + ? GREEN_BOLD(" >>> ") WHITE_BOLD("ALGO CHANGE: ") CYAN_BOLD("%s") + : " >>> ALGO CHANGE: %s", + algorithm.name() + ); + + size_t ways = 0; + for (const xmrig::IThread *thread : threads) { + ways += thread->multiway(); + } + + m_threadsCount = threads.size(); + m_hashrate = new Hashrate(m_threadsCount, m_controller); + + contexts.resize(m_threadsCount); + + for (size_t i = 0; i < m_threadsCount; ++i) { + const OclThread *thread = static_cast(threads[i]); + contexts[i] = GpuContext(thread->index(), thread->intensity(), thread->worksize(), thread->stridedIndex(), thread->memChunk(), thread->isCompMode()); + } + + if (InitOpenCL(contexts.data(), m_threadsCount, m_controller->config()) != 0) { + return false; + } + + uint32_t offset = 0; + + size_t i = 0; + for (xmrig::IThread *thread : threads) { + Handle *handle = new Handle(i, thread, &contexts[i], offset, ways); + offset += thread->multiway(); + i++; + + m_workers.push_back(handle); + handle->start(Workers::onReady); + } + + return true; +} void Workers::stop() { @@ -294,12 +362,18 @@ void Workers::onResult(uv_async_t *handle) return; } - cryptonight_ctx *ctx = CryptoNight::createCtx(baton->jobs[0].algorithm().algo()); + xmrig::Algo algo = baton->jobs[0].algorithm().algo(); + cryptonight_ctx *ctx = CryptoNight::createCtx(algo); for (const Job &job : baton->jobs) { JobResult result(job); - if (CryptoNight::hash(job, result, ctx)) { + if (job.algorithm().algo() != algo) { + CryptoNight::freeCtx(ctx); + ctx = CryptoNight::createCtx(algo = job.algorithm().algo()); + } + + if (job.poolId() == -100 || CryptoNight::hash(job, result, ctx)) { baton->results.push_back(result); } else { @@ -317,7 +391,7 @@ void Workers::onResult(uv_async_t *handle) } if (baton->errors > 0 && !baton->jobs.empty()) { - LOG_ERR("THREAD #%d COMPUTE ERROR", baton->jobs[0].threadId()); + LOG_ERR("THREAD #%d COMPUTE ERROR(s): %i", baton->jobs[0].threadId(), baton->errors); } delete baton; diff --git a/src/workers/Workers.h b/src/workers/Workers.h index e58c760a..04e92eda 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -56,6 +57,8 @@ class Workers static void setEnabled(bool enabled); static void setJob(const Job &job, bool donate); static bool start(xmrig::Controller *controller); + // setups workers based on specified algorithm (or its basic perf algo more specifically) + static bool switch_algo(const xmrig::Algorithm&); static void stop(); static void submit(const Job &result); @@ -76,6 +79,7 @@ class Workers static void onResult(uv_async_t *handle); static void onTick(uv_timer_t *handle); static void start(IWorker *worker); + static void soft_stop(); // stop current workers leaving uv stuff intact (used in switch_algo) static bool m_active; static bool m_enabled;