mirror of
https://github.com/xmrig/xmrig.git
synced 2025-12-07 07:55:04 -05:00
Compare commits
49 Commits
v4.1.0-bet
...
v4.2.1-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96b2560f79 | ||
|
|
923d47fff0 | ||
|
|
542a27a032 | ||
|
|
a7e8ac6cf8 | ||
|
|
42fd146c2b | ||
|
|
34468782cd | ||
|
|
3badeb56a0 | ||
|
|
bc18b5d0be | ||
|
|
158d2e4302 | ||
|
|
f60118ee79 | ||
|
|
6bc217e985 | ||
|
|
3560b6a3c2 | ||
|
|
77eecdd2c2 | ||
|
|
f4943b77f3 | ||
|
|
c908ef2489 | ||
|
|
d21155f3c6 | ||
|
|
da39ed2ce0 | ||
|
|
06500761fb | ||
|
|
919a6c0cc4 | ||
|
|
467e5115b0 | ||
|
|
c495802f64 | ||
|
|
66e48ed2d7 | ||
|
|
ac4cd3eb9b | ||
|
|
5d73402651 | ||
|
|
427b6516e0 | ||
|
|
eae9009b98 | ||
|
|
166d8dd53c | ||
|
|
680081b93b | ||
|
|
e66eeefb14 | ||
|
|
8e9e8cd169 | ||
|
|
f96538dfba | ||
|
|
9ad174c129 | ||
|
|
17b40ac4ad | ||
|
|
4453727754 | ||
|
|
d086318f4e | ||
|
|
5b7f1fe853 | ||
|
|
4c357d2d60 | ||
|
|
0eb5588454 | ||
|
|
5ba8b43fb8 | ||
|
|
0eb754d76e | ||
|
|
7c463849cc | ||
|
|
daed23422e | ||
|
|
550e332909 | ||
|
|
43f26dcd76 | ||
|
|
e1d1a5226c | ||
|
|
82aaa89ab6 | ||
|
|
aac384f54f | ||
|
|
3cbbc94249 | ||
|
|
cbc08e696f |
15
CHANGELOG.md
15
CHANGELOG.md
@@ -1,3 +1,14 @@
|
||||
# v4.2.1-beta
|
||||
- [#1150](https://github.com/xmrig/xmrig/issues/1150) Fixed build on FreeBSD.
|
||||
- [#1175](https://github.com/xmrig/xmrig/issues/1175) Fixed support for systems where total count of NUMA nodes not equal usable nodes count.
|
||||
- [#1199](https://github.com/xmrig/xmrig/issues/1199) Fixed excessive memory allocation for OpenCL threads with low intensity.
|
||||
- [#1212](https://github.com/xmrig/xmrig/issues/1212) Fixed low RandomX performance after fast algorithm switching.
|
||||
|
||||
# v4.2.0-beta
|
||||
- [#1202](https://github.com/xmrig/xmrig/issues/1202) Fixed algorithm verification in donate strategy.
|
||||
- Added per pool option `coin` with single possible value `monero` for pools without algorithm negotiation, for upcoming Monero fork.
|
||||
- Added config option `cpu/max-threads-hint` and command line option `--cpu-max-threads-hint`.
|
||||
|
||||
# v4.1.0-beta
|
||||
- **OpenCL backend disabled by default.**.
|
||||
- [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd.
|
||||
@@ -18,6 +29,10 @@
|
||||
- [#268](https://github.com/xmrig/xmrig-amd/pull/268) [#270](https://github.com/xmrig/xmrig-amd/pull/270) [#271](https://github.com/xmrig/xmrig-amd/pull/271) [#273](https://github.com/xmrig/xmrig-amd/pull/273) [#274](https://github.com/xmrig/xmrig-amd/pull/274) [#1171](https://github.com/xmrig/xmrig/pull/1171) Added RandomX support for OpenCL, thanks [@SChernykh](https://github.com/SChernykh).
|
||||
- Algorithm `cn/wow` removed, as no longer alive.
|
||||
|
||||
# v3.2.0
|
||||
- Added per pool option `coin` with single possible value `monero` for pools without algorithm negotiation, for upcoming Monero fork.
|
||||
- [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd.
|
||||
|
||||
# v3.1.3
|
||||
- [#1180](https://github.com/xmrig/xmrig/issues/1180) Fixed possible duplicated shares after algorithm switching.
|
||||
- Fixed wrong config file permissions after write (only gcc builds on recent Windows 10 affected).
|
||||
|
||||
@@ -71,6 +71,7 @@ set(HEADERS_CRYPTO
|
||||
src/crypto/cn/skein_port.h
|
||||
src/crypto/cn/soft_aes.h
|
||||
src/crypto/common/Algorithm.h
|
||||
src/crypto/common/Coin.h
|
||||
src/crypto/common/keccak.h
|
||||
src/crypto/common/Nonce.h
|
||||
src/crypto/common/portable/mm_malloc.h
|
||||
@@ -108,6 +109,7 @@ set(SOURCES_CRYPTO
|
||||
src/crypto/cn/CnCtx.cpp
|
||||
src/crypto/cn/CnHash.cpp
|
||||
src/crypto/common/Algorithm.cpp
|
||||
src/crypto/common/Coin.cpp
|
||||
src/crypto/common/keccak.cpp
|
||||
src/crypto/common/Nonce.cpp
|
||||
src/crypto/common/VirtualMemory.cpp
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# XMRig
|
||||
|
||||
**:warning: [Monero will change PoW algorithm to RandomX on November 30.](https://github.com/xmrig/xmrig/issues/1204)**
|
||||
|
||||
[](https://github.com/xmrig/xmrig/releases)
|
||||
[](https://github.com/xmrig/xmrig/releases)
|
||||
[](https://github.com/xmrig/xmrig/releases)
|
||||
@@ -26,7 +28,7 @@ XMRig is a high performance RandomX and CryptoNight CPU miner, with official sup
|
||||
* Clone with `git clone https://github.com/xmrig/xmrig.git` :hammer: [Build instructions](https://github.com/xmrig/xmrig/wiki/Build).
|
||||
|
||||
## Usage
|
||||
Preferend way to configure miner is [JSON config file](src/config.json) as more flexible and human frendly, command line interface not cover all features, for example mining profiles for different algorithms. Most impotant options can be changed in runtime without miner restart by editing config or via API.
|
||||
The preferred way to configure the miner is the [JSON config file](src/config.json) as it is more flexible and human friendly. The command line interface does not cover all features, such as mining profiles for different algorithms. Important options can be changed during runtime without miner restart by editing the config file or executing API calls.
|
||||
|
||||
### Options
|
||||
```
|
||||
|
||||
@@ -1,34 +1,20 @@
|
||||
# Algorithms
|
||||
|
||||
Since version 3 mining [algorithm](#algorithm-names) should specified for each pool separately (`algo` option), earlier versions was use one global `algo` option and per pool `variant` option (this option was removed in v3). If your pool support [mining algorithm negotiation](https://github.com/xmrig/xmrig-proxy/issues/168) you may not specify this option at all.
|
||||
Algorithm can be defined in 3 ways:
|
||||
|
||||
#### Example
|
||||
```json
|
||||
{
|
||||
"pools": [
|
||||
{
|
||||
"url": "...",
|
||||
"algo": "cn/r",
|
||||
...
|
||||
}
|
||||
],
|
||||
...
|
||||
}
|
||||
```
|
||||
1. By pool, using algorithm negotiation, in this case no need specify algorithm on miner side.
|
||||
2. Per pool `coin` option, currently only usable value for this option is `monero`.
|
||||
3. Per pool `algo` option.
|
||||
|
||||
#### Pools with mining algorithm negotiation support.
|
||||
Option `coin` useful for pools without algorithm negotiation support or daemon to allow automatically switch algorithm in next hard fork.
|
||||
|
||||
* [www.hashvault.pro](https://www.hashvault.pro/)
|
||||
* [moneroocean.stream](https://moneroocean.stream)
|
||||
|
||||
## Algorithm names
|
||||
## Algorithm names
|
||||
|
||||
| Name | Memory | Version | Notes |
|
||||
|------|--------|---------|-------|
|
||||
| `rx/0` | 2 MB | 3.2.0+ | RandomX (Monero). |
|
||||
| `argon2/chukwa` | 512 KB | 3.1.0+ | Argon2id (Chukwa). |
|
||||
| `argon2/wrkz` | 256 KB | 3.1.0+ | Argon2id (WRKZ) |
|
||||
| `rx/test` | 2 MB | 3.0.0+ | RandomX (reference configuration). |
|
||||
| `rx/0` | 2 MB | 3.0.0+ | RandomX (reference configuration), reserved for future use. |
|
||||
| `rx/wow` | 1 MB | 3.0.0+ | RandomWOW. |
|
||||
| `rx/loki` | 2 MB | 3.0.0+ | RandomXL. |
|
||||
| `cn/fast` | 2 MB | 3.0.0+ | CryptoNight variant 1 with half iterations. |
|
||||
@@ -50,3 +36,21 @@ Since version 3 mining [algorithm](#algorithm-names) should specified for each p
|
||||
| `cn-lite/1` | 1 MB | 2.5.0+ | CryptoNight-Lite variant 1. |
|
||||
| `cn-lite/0` | 1 MB | 0.8.0+ | CryptoNight-Lite variant 0. |
|
||||
| `cn/0` | 2 MB | 0.5.0+ | CryptoNight (original). |
|
||||
|
||||
## Migration to v3
|
||||
Since version 3 mining [algorithm](#algorithm-names) should specified for each pool separately (`algo` option), earlier versions was use one global `algo` option and per pool `variant` option (this option was removed in v3). If your pool support [mining algorithm negotiation](https://github.com/xmrig/xmrig-proxy/issues/168) you may not specify this option at all.
|
||||
|
||||
#### Example
|
||||
```json
|
||||
{
|
||||
"pools": [
|
||||
{
|
||||
"url": "...",
|
||||
"algo": "cn/r",
|
||||
"coin": null
|
||||
...
|
||||
}
|
||||
],
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
@@ -94,3 +94,6 @@ Enable/configure or disable ASM optimizations. Possible values: `true`, `false`,
|
||||
|
||||
#### `argon2-impl` (since v3.1.0)
|
||||
Allow override automatically detected Argon2 implementation, this option added mostly for debug purposes, default value `null` means autodetect. Other possible values: `"x86_64"`, `"SSE2"`, `"SSSE3"`, `"XOP"`, `"AVX2"`, `"AVX-512F"`. Manual selection has no safe guards, if you CPU not support required instuctions, miner will crash.
|
||||
|
||||
#### `max-threads-hint` (since v4.2.0)
|
||||
Maximum CPU threads count (in percentage) hint for autoconfig. [CPU_MAX_USAGE.md](CPU_MAX_USAGE.md)
|
||||
|
||||
26
doc/CPU_MAX_USAGE.md
Normal file
26
doc/CPU_MAX_USAGE.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Maximum CPU usage
|
||||
|
||||
Please read this document carefully, `max-threads-hint` (was known as `max-cpu-usage`) option is most confusing option in the miner with many myth and legends.
|
||||
This option is just hint for automatic configuration and can't precise define CPU usage.
|
||||
|
||||
### Option definition
|
||||
#### Config file:
|
||||
```json
|
||||
{
|
||||
...
|
||||
"cpu": {
|
||||
"max-threads-hint": 100,
|
||||
...
|
||||
},
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
#### Command line
|
||||
`--cpu-max-threads-hint 100`
|
||||
|
||||
### Known issues and usage
|
||||
|
||||
* This option has no effect if miner already generated CPU configuration, to prevent config generation use `"autosave":false,`.
|
||||
* Only threads count can be changed, for 1 core CPU this option has no effect, for 2 core CPU only 2 values possible 50% and 100%, for 4 cores: 25%, 50%, 75%, 100%. etc.
|
||||
* You CPU may limited by other factors, eg cache.
|
||||
6
src/3rdparty/argon2/CMakeLists.txt
vendored
6
src/3rdparty/argon2/CMakeLists.txt
vendored
@@ -22,7 +22,7 @@ set(ARGON2_X86_64_SOURCES arch/x86_64/lib/argon2-arch.c arch/x86_64/lib/cpu-flag
|
||||
if (CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
function(add_feature_impl FEATURE MSVC_FLAG DEF)
|
||||
add_library(argon2-${FEATURE} STATIC arch/x86_64/lib/argon2-${FEATURE}.c)
|
||||
target_include_directories(argon2-${FEATURE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_include_directories(argon2-${FEATURE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||
target_include_directories(argon2-${FEATURE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/lib)
|
||||
set_target_properties(argon2-${FEATURE} PROPERTIES POSITION_INDEPENDENT_CODE True)
|
||||
|
||||
@@ -38,7 +38,7 @@ if (CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
elseif (NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
function(add_feature_impl FEATURE GCC_FLAG DEF)
|
||||
add_library(argon2-${FEATURE} STATIC arch/x86_64/lib/argon2-${FEATURE}.c)
|
||||
target_include_directories(argon2-${FEATURE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_include_directories(argon2-${FEATURE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||
target_include_directories(argon2-${FEATURE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/lib)
|
||||
set_target_properties(argon2-${FEATURE} PROPERTIES POSITION_INDEPENDENT_CODE True)
|
||||
|
||||
@@ -84,5 +84,5 @@ endif()
|
||||
add_library(argon2 STATIC ${ARGON2_SOURCES})
|
||||
target_link_libraries(argon2 ${ARGON2_LIBS})
|
||||
|
||||
target_include_directories(argon2 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
target_include_directories(argon2 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||
target_include_directories(argon2 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/lib)
|
||||
|
||||
2
src/3rdparty/argon2/lib/argon2.c
vendored
2
src/3rdparty/argon2/lib/argon2.c
vendored
@@ -15,7 +15,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "argon2.h"
|
||||
#include "3rdparty/argon2.h"
|
||||
#include "encoding.h"
|
||||
#include "core.h"
|
||||
|
||||
|
||||
2
src/3rdparty/argon2/lib/core.h
vendored
2
src/3rdparty/argon2/lib/core.h
vendored
@@ -14,7 +14,7 @@
|
||||
#ifndef ARGON2_CORE_H
|
||||
#define ARGON2_CORE_H
|
||||
|
||||
#include "argon2.h"
|
||||
#include "3rdparty/argon2.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ALIGN(n) __declspec(align(16))
|
||||
|
||||
2
src/3rdparty/argon2/lib/encoding.h
vendored
2
src/3rdparty/argon2/lib/encoding.h
vendored
@@ -1,6 +1,6 @@
|
||||
#ifndef ENCODING_H
|
||||
#define ENCODING_H
|
||||
#include "argon2.h"
|
||||
#include "3rdparty/argon2.h"
|
||||
|
||||
#define ARGON2_MAX_DECODED_LANES UINT32_C(255)
|
||||
#define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8)
|
||||
|
||||
2
src/3rdparty/argon2/lib/impl-select.c
vendored
2
src/3rdparty/argon2/lib/impl-select.c
vendored
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "impl-select.h"
|
||||
|
||||
#include "argon2.h"
|
||||
#include "3rdparty/argon2.h"
|
||||
|
||||
#define BENCH_SAMPLES 1024
|
||||
#define BENCH_MEM_BLOCKS 512
|
||||
|
||||
@@ -44,6 +44,7 @@ class Threads
|
||||
public:
|
||||
inline bool has(const char *profile) const { return m_profiles.count(profile) > 0; }
|
||||
inline bool isDisabled(const Algorithm &algo) const { return m_disabled.count(algo) > 0; }
|
||||
inline bool isEmpty() const { return m_profiles.empty(); }
|
||||
inline bool isExist(const Algorithm &algo) const { return isDisabled(algo) || m_aliases.count(algo) > 0 || has(algo.shortName()); }
|
||||
inline const T &get(const Algorithm &algo, bool strict = false) const { return get(profileName(algo, strict)); }
|
||||
inline void disable(const Algorithm &algo) { m_disabled.insert(algo); }
|
||||
|
||||
@@ -100,6 +100,7 @@ void xmrig::Workers<T>::start(const std::vector<T> &data)
|
||||
}
|
||||
|
||||
d_ptr->hashrate = new Hashrate(m_workers.size());
|
||||
Nonce::touch(T::backend());
|
||||
|
||||
for (Thread<T> *worker : m_workers) {
|
||||
worker->start(Workers<T>::onReady);
|
||||
|
||||
@@ -35,6 +35,7 @@ static const char *kCn = "cn";
|
||||
static const char *kEnabled = "enabled";
|
||||
static const char *kHugePages = "huge-pages";
|
||||
static const char *kHwAes = "hw-aes";
|
||||
static const char *kMaxThreadsHint = "max-threads-hint";
|
||||
static const char *kPriority = "priority";
|
||||
|
||||
#ifdef XMRIG_FEATURE_ASM
|
||||
@@ -72,11 +73,6 @@ extern template class Threads<CpuThreads>;
|
||||
}
|
||||
|
||||
|
||||
xmrig::CpuConfig::CpuConfig()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::CpuConfig::isHwAES() const
|
||||
{
|
||||
return (m_aes == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aes) == AES_HW;
|
||||
@@ -95,6 +91,10 @@ rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const
|
||||
obj.AddMember(StringRef(kHwAes), m_aes == AES_AUTO ? Value(kNullType) : Value(m_aes == AES_HW), allocator);
|
||||
obj.AddMember(StringRef(kPriority), priority() != -1 ? Value(priority()) : Value(kNullType), allocator);
|
||||
|
||||
if (m_threads.isEmpty()) {
|
||||
obj.AddMember(StringRef(kMaxThreadsHint), m_limit, allocator);
|
||||
}
|
||||
|
||||
# ifdef XMRIG_FEATURE_ASM
|
||||
obj.AddMember(StringRef(kAsm), m_assembly.toJSON(), allocator);
|
||||
# endif
|
||||
@@ -133,6 +133,7 @@ void xmrig::CpuConfig::read(const rapidjson::Value &value, uint32_t version)
|
||||
if (value.IsObject()) {
|
||||
m_enabled = Json::getBool(value, kEnabled, m_enabled);
|
||||
m_hugePages = Json::getBool(value, kHugePages, m_hugePages);
|
||||
m_limit = Json::getUint(value, kMaxThreadsHint, m_limit);
|
||||
|
||||
setAesMode(Json::getValue(value, kHwAes));
|
||||
setPriority(Json::getInt(value, kPriority, -1));
|
||||
@@ -168,28 +169,28 @@ void xmrig::CpuConfig::generate()
|
||||
ICpuInfo *cpu = Cpu::info();
|
||||
|
||||
m_threads.disable(Algorithm::CN_0);
|
||||
m_threads.move(kCn, cpu->threads(Algorithm::CN_0));
|
||||
m_threads.move(kCn, cpu->threads(Algorithm::CN_0, m_limit));
|
||||
|
||||
# ifdef XMRIG_ALGO_CN_GPU
|
||||
m_threads.move(kCnGPU, cpu->threads(Algorithm::CN_GPU));
|
||||
m_threads.move(kCnGPU, cpu->threads(Algorithm::CN_GPU, m_limit));
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_ALGO_CN_LITE
|
||||
m_threads.disable(Algorithm::CN_LITE_0);
|
||||
m_threads.move(kCnLite, cpu->threads(Algorithm::CN_LITE_1));
|
||||
m_threads.move(kCnLite, cpu->threads(Algorithm::CN_LITE_1, m_limit));
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_ALGO_CN_HEAVY
|
||||
m_threads.move(kCnHeavy, cpu->threads(Algorithm::CN_HEAVY_0));
|
||||
m_threads.move(kCnHeavy, cpu->threads(Algorithm::CN_HEAVY_0, m_limit));
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_ALGO_CN_PICO
|
||||
m_threads.move(kCnPico, cpu->threads(Algorithm::CN_PICO_0));
|
||||
m_threads.move(kCnPico, cpu->threads(Algorithm::CN_PICO_0, m_limit));
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
m_threads.move(kRx, cpu->threads(Algorithm::RX_0));
|
||||
m_threads.move(kRxWOW, cpu->threads(Algorithm::RX_WOW));
|
||||
m_threads.move(kRx, cpu->threads(Algorithm::RX_0, m_limit));
|
||||
m_threads.move(kRxWOW, cpu->threads(Algorithm::RX_WOW, m_limit));
|
||||
# endif
|
||||
|
||||
generateArgon2();
|
||||
@@ -199,7 +200,7 @@ void xmrig::CpuConfig::generate()
|
||||
void xmrig::CpuConfig::generateArgon2()
|
||||
{
|
||||
# ifdef XMRIG_ALGO_ARGON2
|
||||
m_threads.move(kArgon2, Cpu::info()->threads(Algorithm::AR2_CHUKWA));
|
||||
m_threads.move(kArgon2, Cpu::info()->threads(Algorithm::AR2_CHUKWA, m_limit));
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
AES_SOFT
|
||||
};
|
||||
|
||||
CpuConfig();
|
||||
CpuConfig() = default;
|
||||
|
||||
bool isHwAES() const;
|
||||
rapidjson::Value toJSON(rapidjson::Document &doc) const;
|
||||
@@ -74,6 +74,7 @@ private:
|
||||
int m_priority = -1;
|
||||
String m_argon2Impl;
|
||||
Threads<CpuThreads> m_threads;
|
||||
uint32_t m_limit = 100;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
virtual bool hasAVX2() const = 0;
|
||||
virtual const char *backend() const = 0;
|
||||
virtual const char *brand() const = 0;
|
||||
virtual CpuThreads threads(const Algorithm &algorithm) const = 0;
|
||||
virtual CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const = 0;
|
||||
virtual size_t cores() const = 0;
|
||||
virtual size_t L2() const = 0;
|
||||
virtual size_t L3() const = 0;
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
#include "3rdparty/libcpuid/libcpuid.h"
|
||||
@@ -109,7 +109,7 @@ xmrig::AdvancedCpuInfo::AdvancedCpuInfo() :
|
||||
}
|
||||
|
||||
|
||||
xmrig::CpuThreads xmrig::AdvancedCpuInfo::threads(const Algorithm &algorithm) const
|
||||
xmrig::CpuThreads xmrig::AdvancedCpuInfo::threads(const Algorithm &algorithm, uint32_t limit) const
|
||||
{
|
||||
if (threads() == 1) {
|
||||
return 1;
|
||||
@@ -153,5 +153,12 @@ xmrig::CpuThreads xmrig::AdvancedCpuInfo::threads(const Algorithm &algorithm) co
|
||||
}
|
||||
# endif
|
||||
|
||||
return CpuThreads(std::max<size_t>(std::min<size_t>(count, threads()), 1), intensity);
|
||||
if (limit > 0 && limit < 100) {
|
||||
count = std::min(count, static_cast<size_t>(round(threads() * (limit / 100.0))));
|
||||
}
|
||||
else {
|
||||
count = std::min(count, threads());
|
||||
}
|
||||
|
||||
return CpuThreads(std::max<size_t>(count, 1), intensity);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
AdvancedCpuInfo();
|
||||
|
||||
protected:
|
||||
CpuThreads threads(const Algorithm &algorithm) const override;
|
||||
CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const override;
|
||||
|
||||
inline Assembly::Id assembly() const override { return m_assembly; }
|
||||
inline bool hasAES() const override { return m_aes; }
|
||||
|
||||
@@ -179,7 +179,7 @@ const char *xmrig::BasicCpuInfo::backend() const
|
||||
}
|
||||
|
||||
|
||||
xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm) const
|
||||
xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm, uint32_t limit) const
|
||||
{
|
||||
const size_t count = std::thread::hardware_concurrency();
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
|
||||
protected:
|
||||
const char *backend() const override;
|
||||
CpuThreads threads(const Algorithm &algorithm) const override;
|
||||
CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const override;
|
||||
|
||||
inline Assembly::Id assembly() const override { return m_assembly; }
|
||||
inline bool hasAES() const override { return m_aes; }
|
||||
|
||||
@@ -63,7 +63,7 @@ const char *xmrig::BasicCpuInfo::backend() const
|
||||
}
|
||||
|
||||
|
||||
xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &) const
|
||||
xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &, uint32_t) const
|
||||
{
|
||||
return CpuThreads(threads());
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <hwloc.h>
|
||||
|
||||
|
||||
@@ -127,9 +128,7 @@ static inline bool isCacheExclusive(hwloc_obj_t obj)
|
||||
} // namespace xmrig
|
||||
|
||||
|
||||
xmrig::HwlocCpuInfo::HwlocCpuInfo() : BasicCpuInfo(),
|
||||
m_backend(),
|
||||
m_cache()
|
||||
xmrig::HwlocCpuInfo::HwlocCpuInfo()
|
||||
{
|
||||
m_threads = 0;
|
||||
|
||||
@@ -149,7 +148,7 @@ xmrig::HwlocCpuInfo::HwlocCpuInfo() : BasicCpuInfo(),
|
||||
# endif
|
||||
|
||||
const std::vector<hwloc_obj_t> packages = findByType(hwloc_get_root_obj(m_topology), HWLOC_OBJ_PACKAGE);
|
||||
if (packages.size()) {
|
||||
if (!packages.empty()) {
|
||||
const char *value = hwloc_obj_get_info_by_name(packages[0], "CPUModel");
|
||||
if (value) {
|
||||
strncpy(m_brand, value, 64);
|
||||
@@ -178,7 +177,7 @@ xmrig::HwlocCpuInfo::HwlocCpuInfo() : BasicCpuInfo(),
|
||||
|
||||
m_threads = countByType(m_topology, HWLOC_OBJ_PU);
|
||||
m_cores = countByType(m_topology, HWLOC_OBJ_CORE);
|
||||
m_nodes = std::max<size_t>(countByType(m_topology, HWLOC_OBJ_NUMANODE), 1);
|
||||
m_nodes = std::max(hwloc_bitmap_weight(hwloc_topology_get_complete_nodeset(m_topology)), 1);
|
||||
m_packages = countByType(m_topology, HWLOC_OBJ_PACKAGE);
|
||||
|
||||
if (m_nodes > 1) {
|
||||
@@ -202,10 +201,10 @@ xmrig::HwlocCpuInfo::~HwlocCpuInfo()
|
||||
}
|
||||
|
||||
|
||||
xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm) const
|
||||
xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm, uint32_t limit) const
|
||||
{
|
||||
if (L2() == 0 && L3() == 0) {
|
||||
return BasicCpuInfo::threads(algorithm);
|
||||
return BasicCpuInfo::threads(algorithm, limit);
|
||||
}
|
||||
|
||||
const unsigned depth = L3() > 0 ? 3 : 2;
|
||||
@@ -218,21 +217,37 @@ xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm) const
|
||||
|
||||
findCache(hwloc_get_root_obj(m_topology), depth, depth, [&caches](hwloc_obj_t found) { caches.emplace_back(found); });
|
||||
|
||||
if (limit > 0 && limit < 100 && !caches.empty()) {
|
||||
const double maxTotalThreads = round(m_threads * (limit / 100.0));
|
||||
const auto maxPerCache = std::max(static_cast<int>(round(maxTotalThreads / caches.size())), 1);
|
||||
int remaining = std::max(static_cast<int>(maxTotalThreads), 1);
|
||||
|
||||
for (hwloc_obj_t cache : caches) {
|
||||
processTopLevelCache(cache, algorithm, threads);
|
||||
processTopLevelCache(cache, algorithm, threads, std::min(maxPerCache, remaining));
|
||||
|
||||
remaining -= maxPerCache;
|
||||
if (remaining <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (hwloc_obj_t cache : caches) {
|
||||
processTopLevelCache(cache, algorithm, threads, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (threads.isEmpty()) {
|
||||
LOG_WARN("hwloc auto configuration for algorithm \"%s\" failed.", algorithm.shortName());
|
||||
|
||||
return BasicCpuInfo::threads(algorithm);
|
||||
return BasicCpuInfo::threads(algorithm, limit);
|
||||
}
|
||||
|
||||
return threads;
|
||||
}
|
||||
|
||||
|
||||
void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorithm &algorithm, CpuThreads &threads) const
|
||||
void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorithm &algorithm, CpuThreads &threads, size_t limit) const
|
||||
{
|
||||
constexpr size_t oneMiB = 1024u * 1024u;
|
||||
|
||||
@@ -296,6 +311,10 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith
|
||||
}
|
||||
# endif
|
||||
|
||||
if (limit > 0) {
|
||||
cacheHashes = std::min(cacheHashes, limit);
|
||||
}
|
||||
|
||||
if (cacheHashes >= PUs) {
|
||||
for (hwloc_obj_t core : cores) {
|
||||
const std::vector<hwloc_obj_t> units = findByType(core, HWLOC_OBJ_PU);
|
||||
|
||||
@@ -27,10 +27,11 @@
|
||||
|
||||
|
||||
#include "backend/cpu/platform/BasicCpuInfo.h"
|
||||
#include "base/tools/Object.h"
|
||||
|
||||
|
||||
typedef struct hwloc_obj *hwloc_obj_t;
|
||||
typedef struct hwloc_topology *hwloc_topology_t;
|
||||
using hwloc_obj_t = struct hwloc_obj *;
|
||||
using hwloc_topology_t = struct hwloc_topology *;
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
@@ -39,6 +40,9 @@ namespace xmrig {
|
||||
class HwlocCpuInfo : public BasicCpuInfo
|
||||
{
|
||||
public:
|
||||
XMRIG_DISABLE_COPY_MOVE(HwlocCpuInfo)
|
||||
|
||||
|
||||
enum Feature : uint32_t {
|
||||
SET_THISTHREAD_MEMBIND = 1
|
||||
};
|
||||
@@ -51,7 +55,7 @@ public:
|
||||
static inline const std::vector<uint32_t> &nodeIndexes() { return m_nodeIndexes; }
|
||||
|
||||
protected:
|
||||
CpuThreads threads(const Algorithm &algorithm) const override;
|
||||
CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const override;
|
||||
|
||||
inline const char *backend() const override { return m_backend; }
|
||||
inline size_t cores() const override { return m_cores; }
|
||||
@@ -61,14 +65,14 @@ protected:
|
||||
inline size_t packages() const override { return m_packages; }
|
||||
|
||||
private:
|
||||
void processTopLevelCache(hwloc_obj_t obj, const Algorithm &algorithm, CpuThreads &threads) const;
|
||||
void processTopLevelCache(hwloc_obj_t obj, const Algorithm &algorithm, CpuThreads &threads, size_t limit) const;
|
||||
|
||||
static std::vector<uint32_t> m_nodeIndexes;
|
||||
static uint32_t m_features;
|
||||
|
||||
char m_backend[20];
|
||||
hwloc_topology_t m_topology;
|
||||
size_t m_cache[5];
|
||||
char m_backend[20] = { 0 };
|
||||
hwloc_topology_t m_topology = nullptr;
|
||||
size_t m_cache[5] = { 0 };
|
||||
size_t m_cores = 0;
|
||||
size_t m_nodes = 0;
|
||||
size_t m_packages = 0;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "backend/opencl/OclConfig.h"
|
||||
#include "backend/opencl/OclLaunchData.h"
|
||||
#include "backend/opencl/OclWorker.h"
|
||||
#include "backend/opencl/runners/tools/OclSharedState.h"
|
||||
#include "backend/opencl/wrappers/OclContext.h"
|
||||
#include "backend/opencl/wrappers/OclLib.h"
|
||||
#include "base/io/log/Log.h"
|
||||
@@ -164,7 +165,7 @@ public:
|
||||
}
|
||||
|
||||
|
||||
inline void start()
|
||||
inline void start(const Job &job)
|
||||
{
|
||||
LOG_INFO("%s use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" threads)") " scratchpad " CYAN_BOLD("%zu KB"),
|
||||
tag,
|
||||
@@ -194,6 +195,8 @@ public:
|
||||
i++;
|
||||
}
|
||||
|
||||
OclSharedState::start(threads, job);
|
||||
|
||||
status.start(threads.size());
|
||||
workers.start(threads);
|
||||
}
|
||||
@@ -329,7 +332,7 @@ void xmrig::OclBackend::setJob(const Job &job)
|
||||
return stop();
|
||||
}
|
||||
|
||||
if (!d_ptr->context.init(d_ptr->devices, threads, job)) {
|
||||
if (!d_ptr->context.init(d_ptr->devices, threads)) {
|
||||
LOG_WARN("%s " RED_BOLD("disabled") YELLOW(" (OpenCL context unavailable)"), tag);
|
||||
|
||||
return stop();
|
||||
@@ -338,7 +341,7 @@ void xmrig::OclBackend::setJob(const Job &job)
|
||||
stop();
|
||||
|
||||
d_ptr->threads = std::move(threads);
|
||||
d_ptr->start();
|
||||
d_ptr->start(job);
|
||||
}
|
||||
|
||||
|
||||
@@ -371,6 +374,8 @@ void xmrig::OclBackend::stop()
|
||||
d_ptr->workers.stop();
|
||||
d_ptr->threads.clear();
|
||||
|
||||
OclSharedState::release();
|
||||
|
||||
LOG_INFO("%s" YELLOW(" stopped") BLACK_BOLD(" (%" PRIu64 " ms)"), tag, Chrono::steadyMSecs() - ts);
|
||||
}
|
||||
|
||||
|
||||
@@ -193,32 +193,13 @@ std::vector<xmrig::OclLaunchData> xmrig::OclConfig::get(const Miner *miner, cons
|
||||
continue;
|
||||
}
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
auto dataset = algorithm.family() == Algorithm::RANDOM_X ? std::make_shared<OclRxDataset>() : nullptr;
|
||||
# endif
|
||||
|
||||
if (thread.threads().size() > 1) {
|
||||
auto interleave = std::make_shared<OclInterleave>(thread.threads().size());
|
||||
|
||||
for (int64_t affinity : thread.threads()) {
|
||||
OclLaunchData data(miner, algorithm, *this, platform, thread, devices[thread.index()], affinity);
|
||||
data.interleave = interleave;
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
data.dataset = dataset;
|
||||
# endif
|
||||
|
||||
out.emplace_back(std::move(data));
|
||||
out.emplace_back(miner, algorithm, *this, platform, thread, devices[thread.index()], affinity);
|
||||
}
|
||||
}
|
||||
else {
|
||||
OclLaunchData data(miner, algorithm, *this, platform, thread, devices[thread.index()], thread.threads().front());
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
data.dataset = dataset;
|
||||
# endif
|
||||
|
||||
out.emplace_back(std::move(data));
|
||||
out.emplace_back(miner, algorithm, *this, platform, thread, devices[thread.index()], thread.threads().front());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,19 +27,14 @@
|
||||
#define XMRIG_OCLLAUNCHDATA_H
|
||||
|
||||
|
||||
#include "backend/opencl/OclInterleave.h"
|
||||
#include "backend/opencl/OclThread.h"
|
||||
#include "backend/opencl/runners/tools/OclSharedData.h"
|
||||
#include "backend/opencl/wrappers/OclDevice.h"
|
||||
#include "backend/opencl/wrappers/OclPlatform.h"
|
||||
#include "crypto/common/Algorithm.h"
|
||||
#include "crypto/common/Nonce.h"
|
||||
|
||||
|
||||
#ifdef XMRIG_ALGO_RANDOMX
|
||||
# include "backend/opencl/runners/tools/OclRxDataset.h"
|
||||
#endif
|
||||
|
||||
|
||||
using cl_context = struct _cl_context *;
|
||||
|
||||
|
||||
@@ -72,11 +67,6 @@ public:
|
||||
const OclDevice device;
|
||||
const OclPlatform platform;
|
||||
const OclThread thread;
|
||||
OclInterleavePtr interleave;
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
OclRxDatasetPtr dataset;
|
||||
# endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include "backend/common/Tags.h"
|
||||
#include "backend/opencl/runners/OclCnRunner.h"
|
||||
#include "backend/opencl/runners/tools/OclSharedData.h"
|
||||
#include "backend/opencl/runners/tools/OclSharedState.h"
|
||||
#include "base/io/log/Log.h"
|
||||
#include "base/tools/Chrono.h"
|
||||
#include "core/Miner.h"
|
||||
@@ -75,7 +77,7 @@ xmrig::OclWorker::OclWorker(size_t id, const OclLaunchData &data) :
|
||||
m_algorithm(data.algorithm),
|
||||
m_miner(data.miner),
|
||||
m_intensity(data.thread.intensity()),
|
||||
m_interleave(data.interleave)
|
||||
m_sharedData(OclSharedState::get(data.device.index()))
|
||||
{
|
||||
switch (m_algorithm.family()) {
|
||||
case Algorithm::RANDOM_X:
|
||||
@@ -149,9 +151,7 @@ void xmrig::OclWorker::start()
|
||||
|
||||
while (Nonce::sequence(Nonce::OPENCL) > 0) {
|
||||
if (!isReady()) {
|
||||
if (m_interleave) {
|
||||
m_interleave->setResumeCounter(0);
|
||||
}
|
||||
m_sharedData.setResumeCounter(0);
|
||||
|
||||
do {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
@@ -162,9 +162,7 @@ void xmrig::OclWorker::start()
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_interleave) {
|
||||
m_interleave->resumeDelay(m_id);
|
||||
}
|
||||
m_sharedData.resumeDelay(m_id);
|
||||
|
||||
if (!consumeJob()) {
|
||||
return;
|
||||
@@ -172,9 +170,7 @@ void xmrig::OclWorker::start()
|
||||
}
|
||||
|
||||
while (!Nonce::isOutdated(Nonce::OPENCL, m_job.sequence())) {
|
||||
if (m_interleave) {
|
||||
m_interleave->adjustDelay(m_id);
|
||||
}
|
||||
m_sharedData.adjustDelay(m_id);
|
||||
|
||||
const uint64_t t = Chrono::steadyMSecs();
|
||||
|
||||
@@ -233,9 +229,7 @@ void xmrig::OclWorker::storeStats(uint64_t t)
|
||||
|
||||
m_count += m_intensity;
|
||||
|
||||
if (m_interleave) {
|
||||
m_interleave->setRunTime(Chrono::steadyMSecs() - t);
|
||||
}
|
||||
m_sharedData.setRunTime(Chrono::steadyMSecs() - t);
|
||||
|
||||
Worker::storeStats();
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ private:
|
||||
const Miner *m_miner;
|
||||
const uint32_t m_intensity;
|
||||
IOclRunner *m_runner = nullptr;
|
||||
OclInterleavePtr m_interleave;
|
||||
OclSharedData &m_sharedData;
|
||||
WorkerJob<1> m_job;
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ if (WITH_OPENCL)
|
||||
src/backend/opencl/OclCache.h
|
||||
src/backend/opencl/OclConfig.h
|
||||
src/backend/opencl/OclGenerator.h
|
||||
src/backend/opencl/OclInterleave.h
|
||||
src/backend/opencl/OclLaunchData.h
|
||||
src/backend/opencl/OclThread.h
|
||||
src/backend/opencl/OclThreads.h
|
||||
@@ -22,6 +21,8 @@ if (WITH_OPENCL)
|
||||
src/backend/opencl/runners/OclBaseRunner.h
|
||||
src/backend/opencl/runners/OclCnRunner.h
|
||||
src/backend/opencl/runners/tools/OclCnR.h
|
||||
src/backend/opencl/runners/tools/OclSharedData.h
|
||||
src/backend/opencl/runners/tools/OclSharedState.h
|
||||
src/backend/opencl/wrappers/OclContext.h
|
||||
src/backend/opencl/wrappers/OclDevice.h
|
||||
src/backend/opencl/wrappers/OclError.h
|
||||
@@ -42,7 +43,6 @@ if (WITH_OPENCL)
|
||||
src/backend/opencl/OclBackend.cpp
|
||||
src/backend/opencl/OclCache.cpp
|
||||
src/backend/opencl/OclConfig.cpp
|
||||
src/backend/opencl/OclInterleave.cpp
|
||||
src/backend/opencl/OclLaunchData.cpp
|
||||
src/backend/opencl/OclThread.cpp
|
||||
src/backend/opencl/OclThreads.cpp
|
||||
@@ -50,6 +50,8 @@ if (WITH_OPENCL)
|
||||
src/backend/opencl/runners/OclBaseRunner.cpp
|
||||
src/backend/opencl/runners/OclCnRunner.cpp
|
||||
src/backend/opencl/runners/tools/OclCnR.cpp
|
||||
src/backend/opencl/runners/tools/OclSharedData.cpp
|
||||
src/backend/opencl/runners/tools/OclSharedState.cpp
|
||||
src/backend/opencl/wrappers/OclContext.cpp
|
||||
src/backend/opencl/wrappers/OclDevice.cpp
|
||||
src/backend/opencl/wrappers/OclError.cpp
|
||||
@@ -78,7 +80,6 @@ if (WITH_OPENCL)
|
||||
src/backend/opencl/runners/OclRxBaseRunner.h
|
||||
src/backend/opencl/runners/OclRxJitRunner.h
|
||||
src/backend/opencl/runners/OclRxVmRunner.h
|
||||
src/backend/opencl/runners/tools/OclRxDataset.h
|
||||
)
|
||||
|
||||
list(APPEND SOURCES_BACKEND_OPENCL
|
||||
@@ -95,7 +96,6 @@ if (WITH_OPENCL)
|
||||
src/backend/opencl/runners/OclRxBaseRunner.cpp
|
||||
src/backend/opencl/runners/OclRxJitRunner.cpp
|
||||
src/backend/opencl/runners/OclRxVmRunner.cpp
|
||||
src/backend/opencl/runners/tools/OclRxDataset.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -23,10 +23,11 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "backend/opencl/runners/OclBaseRunner.h"
|
||||
#include "backend/opencl/cl/OclSource.h"
|
||||
#include "backend/opencl/OclCache.h"
|
||||
#include "backend/opencl/OclLaunchData.h"
|
||||
#include "backend/opencl/runners/OclBaseRunner.h"
|
||||
#include "backend/opencl/runners/tools/OclSharedState.h"
|
||||
#include "backend/opencl/wrappers/OclError.h"
|
||||
#include "backend/opencl/wrappers/OclLib.h"
|
||||
#include "base/io/log/Log.h"
|
||||
@@ -34,6 +35,9 @@
|
||||
#include "crypto/common/VirtualMemory.h"
|
||||
|
||||
|
||||
constexpr size_t oneGiB = 1024 * 1024 * 1024;
|
||||
|
||||
|
||||
xmrig::OclBaseRunner::OclBaseRunner(size_t id, const OclLaunchData &data) :
|
||||
m_algorithm(data.algorithm),
|
||||
m_ctx(data.ctx),
|
||||
@@ -95,14 +99,15 @@ void xmrig::OclBaseRunner::init()
|
||||
{
|
||||
m_queue = OclLib::createCommandQueue(m_ctx, data().device.id());
|
||||
|
||||
constexpr size_t oneGiB = 1024 * 1024 * 1024;
|
||||
size_t size = bufferSize();
|
||||
size_t size = align(bufferSize());
|
||||
|
||||
if (size < oneGiB && data().device.vendorId() == OCL_VENDOR_AMD && data().device.freeMemSize() >= oneGiB) {
|
||||
size = oneGiB;
|
||||
m_buffer = OclSharedState::get(data().device.index()).createBuffer(m_ctx, size, m_offset);
|
||||
}
|
||||
else {
|
||||
m_buffer = OclLib::createBuffer(m_ctx, CL_MEM_READ_WRITE, size);
|
||||
}
|
||||
|
||||
m_buffer = OclLib::createBuffer(m_ctx, CL_MEM_READ_WRITE, size);
|
||||
m_input = createSubBuffer(CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY, Job::kMaxBlobSize);
|
||||
m_output = createSubBuffer(CL_MEM_READ_WRITE, sizeof(cl_uint) * 0x100);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "backend/opencl/kernels/rx/FindSharesKernel.h"
|
||||
#include "backend/opencl/kernels/rx/HashAesKernel.h"
|
||||
#include "backend/opencl/OclLaunchData.h"
|
||||
#include "backend/opencl/runners/tools/OclSharedState.h"
|
||||
#include "backend/opencl/wrappers/OclLib.h"
|
||||
#include "base/net/stratum/Job.h"
|
||||
#include "crypto/rx/Rx.h"
|
||||
@@ -75,6 +76,7 @@ xmrig::OclRxBaseRunner::~OclRxBaseRunner()
|
||||
OclLib::release(m_hashes);
|
||||
OclLib::release(m_rounding);
|
||||
OclLib::release(m_scratchpads);
|
||||
OclLib::release(m_dataset);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +122,7 @@ void xmrig::OclRxBaseRunner::set(const Job &job, uint8_t *blob)
|
||||
m_seed = job.seed();
|
||||
|
||||
auto dataset = Rx::dataset(job, 0);
|
||||
enqueueWriteBuffer(data().dataset->get(), CL_TRUE, 0, dataset->size(), dataset->raw());
|
||||
enqueueWriteBuffer(m_dataset, CL_TRUE, 0, dataset->size(), dataset->raw());
|
||||
}
|
||||
|
||||
if (job.size() < Job::kMaxBlobSize) {
|
||||
@@ -177,4 +179,5 @@ void xmrig::OclRxBaseRunner::init()
|
||||
m_hashes = createSubBuffer(CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS, 64 * m_intensity);
|
||||
m_entropy = createSubBuffer(CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS, (128 + 2560) * m_intensity);
|
||||
m_rounding = createSubBuffer(CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS, sizeof(uint32_t) * m_intensity);
|
||||
m_dataset = OclSharedState::get(data().device.index()).dataset();
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ protected:
|
||||
Blake2bHashRegistersKernel *m_blake2b_hash_registers_64 = nullptr;
|
||||
Blake2bInitialHashKernel *m_blake2b_initial_hash = nullptr;
|
||||
Buffer m_seed;
|
||||
cl_mem m_dataset = nullptr;
|
||||
cl_mem m_entropy = nullptr;
|
||||
cl_mem m_hashes = nullptr;
|
||||
cl_mem m_rounding = nullptr;
|
||||
|
||||
@@ -74,7 +74,7 @@ void xmrig::OclRxJitRunner::build()
|
||||
}
|
||||
|
||||
m_randomx_run = new RxRunKernel(m_asmProgram);
|
||||
m_randomx_run->setArgs(data().dataset->get(), m_scratchpads, m_registers, m_rounding, m_programs, m_intensity, m_algorithm);
|
||||
m_randomx_run->setArgs(m_dataset, m_scratchpads, m_registers, m_rounding, m_programs, m_intensity, m_algorithm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ void xmrig::OclRxVmRunner::build()
|
||||
m_init_vm->setArgs(m_entropy, m_vm_states, m_rounding);
|
||||
|
||||
m_execute_vm = new ExecuteVmKernel(m_program);
|
||||
m_execute_vm->setArgs(m_vm_states, m_rounding, m_scratchpads, data().dataset->get(), m_intensity);
|
||||
m_execute_vm->setArgs(m_vm_states, m_rounding, m_scratchpads, m_dataset, m_intensity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,17 +23,44 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "backend/opencl/OclInterleave.h"
|
||||
#include "backend/opencl/runners/tools/OclSharedData.h"
|
||||
#include "backend/opencl/wrappers/OclLib.h"
|
||||
#include "base/io/log/Log.h"
|
||||
#include "base/tools/Chrono.h"
|
||||
#include "crypto/rx/Rx.h"
|
||||
#include "crypto/rx/RxDataset.h"
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
|
||||
|
||||
uint64_t xmrig::OclInterleave::adjustDelay(size_t id)
|
||||
constexpr size_t oneGiB = 1024 * 1024 * 1024;
|
||||
|
||||
|
||||
cl_mem xmrig::OclSharedData::createBuffer(cl_context context, size_t size, size_t &offset)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
offset += size * m_offset++;
|
||||
size = std::max(size * m_threads, oneGiB);
|
||||
|
||||
if (!m_buffer) {
|
||||
m_buffer = OclLib::createBuffer(context, CL_MEM_READ_WRITE, size);
|
||||
}
|
||||
|
||||
return OclLib::retain(m_buffer);
|
||||
}
|
||||
|
||||
|
||||
uint64_t xmrig::OclSharedData::adjustDelay(size_t id)
|
||||
{
|
||||
if (m_threads < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint64_t t0 = Chrono::steadyMSecs();
|
||||
uint64_t delay = 0;
|
||||
|
||||
@@ -69,8 +96,12 @@ uint64_t xmrig::OclInterleave::adjustDelay(size_t id)
|
||||
}
|
||||
|
||||
|
||||
uint64_t xmrig::OclInterleave::resumeDelay(size_t id)
|
||||
uint64_t xmrig::OclSharedData::resumeDelay(size_t id)
|
||||
{
|
||||
if (m_threads < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t delay = 0;
|
||||
|
||||
{
|
||||
@@ -99,14 +130,28 @@ uint64_t xmrig::OclInterleave::resumeDelay(size_t id)
|
||||
}
|
||||
|
||||
|
||||
void xmrig::OclInterleave::setResumeCounter(uint32_t value)
|
||||
void xmrig::OclSharedData::release()
|
||||
{
|
||||
OclLib::release(m_buffer);
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
OclLib::release(m_dataset);
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
void xmrig::OclSharedData::setResumeCounter(uint32_t value)
|
||||
{
|
||||
if (m_threads < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_resumeCounter = value;
|
||||
}
|
||||
|
||||
|
||||
void xmrig::OclInterleave::setRunTime(uint64_t time)
|
||||
void xmrig::OclSharedData::setRunTime(uint64_t time)
|
||||
{
|
||||
// averagingBias = 1.0 - only the last delta time is taken into account
|
||||
// averagingBias = 0.5 - the last delta time has the same weight as all the previous ones combined
|
||||
@@ -116,3 +161,34 @@ void xmrig::OclInterleave::setRunTime(uint64_t time)
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_averageRunTime = m_averageRunTime * (1.0 - averagingBias) + time * averagingBias;
|
||||
}
|
||||
|
||||
|
||||
#ifdef XMRIG_ALGO_RANDOMX
|
||||
cl_mem xmrig::OclSharedData::dataset() const
|
||||
{
|
||||
if (!m_dataset) {
|
||||
throw std::runtime_error("RandomX dataset is not available");
|
||||
}
|
||||
|
||||
return OclLib::retain(m_dataset);
|
||||
}
|
||||
|
||||
|
||||
void xmrig::OclSharedData::createDataset(cl_context ctx, const Job &job, bool host)
|
||||
{
|
||||
if (m_dataset) {
|
||||
return;
|
||||
}
|
||||
|
||||
cl_int ret;
|
||||
|
||||
if (host) {
|
||||
auto dataset = Rx::dataset(job, 0);
|
||||
|
||||
m_dataset = OclLib::createBuffer(ctx, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, RxDataset::maxSize(), dataset->raw(), &ret);
|
||||
}
|
||||
else {
|
||||
m_dataset = OclLib::createBuffer(ctx, CL_MEM_READ_ONLY, RxDataset::maxSize(), nullptr, &ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -22,42 +22,62 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef XMRIG_OCLINTERLEAVE_H
|
||||
#define XMRIG_OCLINTERLEAVE_H
|
||||
#ifndef XMRIG_OCLSHAREDDATA_H
|
||||
#define XMRIG_OCLSHAREDDATA_H
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
|
||||
using cl_context = struct _cl_context *;
|
||||
using cl_mem = struct _cl_mem *;
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
class OclInterleave
|
||||
class Job;
|
||||
|
||||
|
||||
class OclSharedData
|
||||
{
|
||||
public:
|
||||
OclInterleave() = delete;
|
||||
inline OclInterleave(size_t threads) : m_threads(threads) {}
|
||||
OclSharedData() = default;
|
||||
|
||||
cl_mem createBuffer(cl_context context, size_t size, size_t &offset);
|
||||
uint64_t adjustDelay(size_t id);
|
||||
uint64_t resumeDelay(size_t id);
|
||||
void release();
|
||||
void setResumeCounter(uint32_t value);
|
||||
void setRunTime(uint64_t time);
|
||||
|
||||
inline size_t threads() const { return m_threads; }
|
||||
|
||||
inline OclSharedData &operator++() { ++m_threads; return *this; }
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
cl_mem dataset() const;
|
||||
void createDataset(cl_context ctx, const Job &job, bool host);
|
||||
# endif
|
||||
|
||||
private:
|
||||
const size_t m_threads;
|
||||
cl_mem m_buffer = nullptr;
|
||||
double m_averageRunTime = 0.0;
|
||||
double m_threshold = 0.95;
|
||||
size_t m_offset = 0;
|
||||
size_t m_threads = 0;
|
||||
std::mutex m_mutex;
|
||||
uint32_t m_resumeCounter = 0;
|
||||
uint64_t m_timestamp = 0;
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
cl_mem m_dataset = nullptr;
|
||||
# endif
|
||||
};
|
||||
|
||||
|
||||
using OclInterleavePtr = std::shared_ptr<OclInterleave>;
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* XMRIG_OCLINTERLEAVE_H */
|
||||
#endif /* XMRIG_OCLSHAREDDATA_H */
|
||||
@@ -23,32 +23,52 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "backend/opencl/runners/tools/OclRxDataset.h"
|
||||
#include "backend/opencl/wrappers/OclLib.h"
|
||||
#include "crypto/rx/Rx.h"
|
||||
#include "crypto/rx/RxDataset.h"
|
||||
#include "backend/opencl/runners/tools/OclSharedState.h"
|
||||
#include "backend/opencl/runners/tools/OclSharedData.h"
|
||||
|
||||
|
||||
void xmrig::OclRxDataset::createBuffer(cl_context ctx, const Job &job, bool host)
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
static std::map<uint32_t, OclSharedData> map;
|
||||
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
|
||||
xmrig::OclSharedData &xmrig::OclSharedState::get(uint32_t index)
|
||||
{
|
||||
if (m_dataset) {
|
||||
return;
|
||||
}
|
||||
|
||||
cl_int ret;
|
||||
|
||||
if (host) {
|
||||
auto dataset = Rx::dataset(job, 0);
|
||||
|
||||
m_dataset = OclLib::createBuffer(ctx, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, RxDataset::maxSize(), dataset->raw(), &ret);
|
||||
}
|
||||
else {
|
||||
m_dataset = OclLib::createBuffer(ctx, CL_MEM_READ_ONLY, RxDataset::maxSize(), nullptr, &ret);
|
||||
}
|
||||
return map[index];
|
||||
}
|
||||
|
||||
|
||||
xmrig::OclRxDataset::~OclRxDataset()
|
||||
void xmrig::OclSharedState::release()
|
||||
{
|
||||
OclLib::release(m_dataset);
|
||||
for (auto &kv : map) {
|
||||
kv.second.release();
|
||||
}
|
||||
|
||||
map.clear();
|
||||
}
|
||||
|
||||
|
||||
void xmrig::OclSharedState::start(const std::vector<OclLaunchData> &threads, const Job &job)
|
||||
{
|
||||
assert(map.empty());
|
||||
|
||||
for (const auto &data : threads) {
|
||||
auto &sharedData = map[data.device.index()];
|
||||
|
||||
++sharedData;
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
if (data.algorithm.family() == Algorithm::RANDOM_X) {
|
||||
sharedData.createDataset(data.ctx, job, data.thread.isDatasetHost());
|
||||
}
|
||||
# endif
|
||||
}
|
||||
}
|
||||
@@ -22,47 +22,26 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef XMRIG_OCLRXDATASET_H
|
||||
#define XMRIG_OCLRXDATASET_H
|
||||
#ifndef XMRIG_OCLSHAREDSTATE_H
|
||||
#define XMRIG_OCLSHAREDSTATE_H
|
||||
|
||||
|
||||
#include "base/tools/Object.h"
|
||||
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
using cl_context = struct _cl_context *;
|
||||
using cl_mem = struct _cl_mem *;
|
||||
#include "backend/opencl/OclLaunchData.h"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
class Job;
|
||||
|
||||
|
||||
class OclRxDataset
|
||||
class OclSharedState
|
||||
{
|
||||
public:
|
||||
XMRIG_DISABLE_COPY_MOVE(OclRxDataset)
|
||||
|
||||
OclRxDataset() = default;
|
||||
~OclRxDataset();
|
||||
|
||||
inline cl_mem get() const { return m_dataset; }
|
||||
|
||||
void createBuffer(cl_context ctx,const Job &job, bool host);
|
||||
|
||||
private:
|
||||
cl_mem m_dataset = nullptr;
|
||||
static OclSharedData &get(uint32_t index);
|
||||
static void release();
|
||||
static void start(const std::vector<OclLaunchData> &threads, const Job &job);
|
||||
};
|
||||
|
||||
|
||||
using OclRxDatasetPtr = std::shared_ptr<OclRxDataset>;
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* XMRIG_OCLINTERLEAVE_H */
|
||||
#endif /* XMRIG_OCLSHAREDSTATE_H */
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
|
||||
#include "backend/opencl/wrappers/OclContext.h"
|
||||
#include "backend/opencl/runners/tools/OclSharedState.h"
|
||||
#include "backend/opencl/wrappers/OclLib.h"
|
||||
|
||||
|
||||
@@ -42,7 +43,7 @@ xmrig::OclContext::~OclContext()
|
||||
}
|
||||
|
||||
|
||||
bool xmrig::OclContext::init(const std::vector<OclDevice> &devices, std::vector<OclLaunchData> &threads, const Job &job)
|
||||
bool xmrig::OclContext::init(const std::vector<OclDevice> &devices, std::vector<OclLaunchData> &threads)
|
||||
{
|
||||
if (!m_ctx) {
|
||||
std::vector<cl_device_id> ids(devices.size());
|
||||
@@ -59,12 +60,6 @@ bool xmrig::OclContext::init(const std::vector<OclDevice> &devices, std::vector<
|
||||
|
||||
for (OclLaunchData &data : threads) {
|
||||
data.ctx = m_ctx;
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
if (data.algorithm.family() == Algorithm::RANDOM_X) {
|
||||
data.dataset->createBuffer(m_ctx, job, data.thread.isDatasetHost());
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
OclContext(const OclDevice &device);
|
||||
~OclContext();
|
||||
|
||||
bool init(const std::vector<OclDevice> &devices, std::vector<OclLaunchData> &threads, const Job &job);
|
||||
bool init(const std::vector<OclDevice> &devices, std::vector<OclLaunchData> &threads);
|
||||
|
||||
inline bool isValid() const { return m_ctx != nullptr; }
|
||||
inline cl_context ctx() const { return m_ctx; }
|
||||
|
||||
@@ -59,7 +59,7 @@ extern bool ocl_vega_cn_generator(const OclDevice &device, const Algorithm &algo
|
||||
extern bool ocl_generic_cn_generator(const OclDevice &device, const Algorithm &algorithm, OclThreads &threads);
|
||||
|
||||
|
||||
ocl_gen_config_fun generators[] = {
|
||||
static ocl_gen_config_fun generators[] = {
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
ocl_generic_rx_generator,
|
||||
# endif
|
||||
@@ -215,6 +215,6 @@ void xmrig::OclDevice::toJSON(rapidjson::Value &out, rapidjson::Document &doc) c
|
||||
out.AddMember("name", name().toJSON(doc), allocator);
|
||||
out.AddMember("bus_id", topology().toString().toJSON(doc), allocator);
|
||||
out.AddMember("cu", computeUnits(), allocator);
|
||||
out.AddMember("global_mem", globalMemSize(), allocator);
|
||||
out.AddMember("global_mem", static_cast<uint64_t>(globalMemSize()), allocator);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -73,6 +73,7 @@ static const char *kReleaseDevice = "clReleaseDevice";
|
||||
static const char *kReleaseKernel = "clReleaseKernel";
|
||||
static const char *kReleaseMemObject = "clReleaseMemObject";
|
||||
static const char *kReleaseProgram = "clReleaseProgram";
|
||||
static const char *kRetainMemObject = "clRetainMemObject";
|
||||
static const char *kRetainProgram = "clRetainProgram";
|
||||
static const char *kSetKernelArg = "clSetKernelArg";
|
||||
static const char *kSetMemObjectDestructorCallback = "clSetMemObjectDestructorCallback";
|
||||
@@ -106,6 +107,7 @@ typedef cl_int (CL_API_CALL *releaseDevice_t)(cl_device_id device);
|
||||
typedef cl_int (CL_API_CALL *releaseKernel_t)(cl_kernel);
|
||||
typedef cl_int (CL_API_CALL *releaseMemObject_t)(cl_mem);
|
||||
typedef cl_int (CL_API_CALL *releaseProgram_t)(cl_program);
|
||||
typedef cl_int (CL_API_CALL *retainMemObject_t)(cl_mem);
|
||||
typedef cl_int (CL_API_CALL *retainProgram_t)(cl_program);
|
||||
typedef cl_int (CL_API_CALL *setKernelArg_t)(cl_kernel, cl_uint, size_t, const void *);
|
||||
typedef cl_int (CL_API_CALL *setMemObjectDestructorCallback_t)(cl_mem, void (CL_CALLBACK *)(cl_mem, void *), void *);
|
||||
@@ -148,6 +150,7 @@ static releaseDevice_t pReleaseDevice = nu
|
||||
static releaseKernel_t pReleaseKernel = nullptr;
|
||||
static releaseMemObject_t pReleaseMemObject = nullptr;
|
||||
static releaseProgram_t pReleaseProgram = nullptr;
|
||||
static retainMemObject_t pRetainMemObject = nullptr;
|
||||
static retainProgram_t pRetainProgram = nullptr;
|
||||
static setKernelArg_t pSetKernelArg = nullptr;
|
||||
static setMemObjectDestructorCallback_t pSetMemObjectDestructorCallback = nullptr;
|
||||
@@ -239,6 +242,7 @@ bool xmrig::OclLib::load()
|
||||
DLSYM(SetMemObjectDestructorCallback);
|
||||
DLSYM(CreateSubBuffer);
|
||||
DLSYM(RetainProgram);
|
||||
DLSYM(RetainMemObject);
|
||||
|
||||
# if defined(CL_VERSION_2_0)
|
||||
uv_dlsym(&oclLib, kCreateCommandQueueWithProperties, reinterpret_cast<void**>(&pCreateCommandQueueWithProperties));
|
||||
@@ -670,6 +674,18 @@ cl_mem xmrig::OclLib::createSubBuffer(cl_mem buffer, cl_mem_flags flags, size_t
|
||||
}
|
||||
|
||||
|
||||
cl_mem xmrig::OclLib::retain(cl_mem memobj) noexcept
|
||||
{
|
||||
assert(pRetainMemObject != nullptr);
|
||||
|
||||
if (memobj != nullptr) {
|
||||
pRetainMemObject(memobj);
|
||||
}
|
||||
|
||||
return memobj;
|
||||
}
|
||||
|
||||
|
||||
cl_program xmrig::OclLib::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) noexcept
|
||||
{
|
||||
assert(pCreateProgramWithBinary != nullptr);
|
||||
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
static cl_mem createBuffer(cl_context context, cl_mem_flags flags, size_t size, void *host_ptr, cl_int *errcode_ret) noexcept;
|
||||
static cl_mem createSubBuffer(cl_mem buffer, cl_mem_flags flags, size_t offset, size_t size, cl_int *errcode_ret) noexcept;
|
||||
static cl_mem createSubBuffer(cl_mem buffer, cl_mem_flags flags, size_t offset, size_t size);
|
||||
static cl_mem retain(cl_mem memobj) noexcept;
|
||||
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) noexcept;
|
||||
static cl_program createProgramWithSource(cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret) noexcept;
|
||||
static cl_program retain(cl_program program) noexcept;
|
||||
|
||||
@@ -73,7 +73,7 @@ rapidjson::Value xmrig::OclPlatform::toJSON(rapidjson::Document &doc) const
|
||||
}
|
||||
|
||||
Value out(kObjectType);
|
||||
out.AddMember("index", index(), allocator);
|
||||
out.AddMember("index", static_cast<uint64_t>(index()), allocator);
|
||||
out.AddMember("profile", profile().toJSON(doc), allocator);
|
||||
out.AddMember("version", version().toJSON(doc), allocator);
|
||||
out.AddMember("name", name().toJSON(doc), allocator);
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace xmrig
|
||||
|
||||
static const char *kAlgo = "algo";
|
||||
static const char *kApi = "api";
|
||||
static const char *kCoin = "coin";
|
||||
static const char *kHttp = "http";
|
||||
static const char *kPools = "pools";
|
||||
|
||||
@@ -103,6 +104,15 @@ void xmrig::BaseTransform::finalize(rapidjson::Document &doc)
|
||||
}
|
||||
}
|
||||
|
||||
if (m_coin.isValid() && doc.HasMember(kPools)) {
|
||||
auto &pools = doc[kPools];
|
||||
for (Value &pool : pools.GetArray()) {
|
||||
if (!pool.HasMember(kCoin)) {
|
||||
pool.AddMember(StringRef(kCoin), m_coin.toJSON(), allocator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_http) {
|
||||
set(doc, kHttp, "enabled", true);
|
||||
}
|
||||
@@ -121,6 +131,15 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
|
||||
}
|
||||
break;
|
||||
|
||||
case IConfig::CoinKey: /* --coin */
|
||||
if (!doc.HasMember(kPools)) {
|
||||
m_coin = arg;
|
||||
}
|
||||
else {
|
||||
return add(doc, kPools, kCoin, arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case IConfig::UserpassKey: /* --userpass */
|
||||
{
|
||||
const char *p = strrchr(arg, ':');
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
|
||||
#include "base/kernel/interfaces/IConfigTransform.h"
|
||||
#include "crypto/common/Coin.h"
|
||||
#include "rapidjson/document.h"
|
||||
|
||||
|
||||
@@ -97,6 +98,7 @@ protected:
|
||||
|
||||
protected:
|
||||
Algorithm m_algorithm;
|
||||
Coin m_coin;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -43,6 +43,7 @@ public:
|
||||
enum Keys {
|
||||
// common
|
||||
AlgorithmKey = 'a',
|
||||
CoinKey = 1025,
|
||||
ApiWorkerIdKey = 4002,
|
||||
ApiIdKey = 4005,
|
||||
HttpPort = 4100,
|
||||
@@ -87,6 +88,7 @@ public:
|
||||
AssemblyKey = 1015,
|
||||
RandomXInitKey = 1022,
|
||||
RandomXNumaKey = 1023,
|
||||
CPUMaxThreadsKey = 1026,
|
||||
|
||||
// xmrig amd
|
||||
OclPlatformKey = 1400,
|
||||
|
||||
@@ -334,6 +334,9 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code)
|
||||
if (algo) {
|
||||
job.setAlgorithm(algo);
|
||||
}
|
||||
else if (m_pool.coin().isValid()) {
|
||||
job.setAlgorithm(m_pool.coin().algorithm(job.blob()[0]));
|
||||
}
|
||||
|
||||
job.setHeight(Json::getUint64(params, "height"));
|
||||
|
||||
@@ -426,7 +429,12 @@ bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm, const char *algo
|
||||
{
|
||||
if (!algorithm.isValid()) {
|
||||
if (!isQuiet()) {
|
||||
LOG_ERR("[%s] Unknown/unsupported algorithm \"%s\" detected, reconnect", url(), algo);
|
||||
if (algo == nullptr) {
|
||||
LOG_ERR("[%s] unknown algorithm, make sure you set \"algo\" or \"coin\" option", url(), algo);
|
||||
}
|
||||
else {
|
||||
LOG_ERR("[%s] unsupported algorithm \"%s\" detected, reconnect", url(), algo);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -436,7 +444,7 @@ bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm, const char *algo
|
||||
m_listener->onVerifyAlgorithm(this, algorithm, &ok);
|
||||
|
||||
if (!ok && !isQuiet()) {
|
||||
LOG_ERR("[%s] Incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algorithm.shortName());
|
||||
LOG_ERR("[%s] incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algorithm.shortName());
|
||||
}
|
||||
|
||||
return ok;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
#include "3rdparty/http-parser/http_parser.h"
|
||||
@@ -225,6 +225,10 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code)
|
||||
job.setDiff(Json::getUint64(params, "difficulty"));
|
||||
job.setId(blocktemplate.data() + blocktemplate.size() - 32);
|
||||
|
||||
if (m_pool.coin().isValid()) {
|
||||
job.setAlgorithm(m_pool.coin().algorithm(job.blob()[0]));
|
||||
}
|
||||
|
||||
m_job = std::move(job);
|
||||
m_blocktemplate = std::move(blocktemplate);
|
||||
m_prevHash = Json::getString(params, "prev_hash");
|
||||
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
inline uint8_t fixedByte() const { return *(m_blob + 42); }
|
||||
inline uint8_t index() const { return m_index; }
|
||||
inline void reset() { m_size = 0; m_diff = 0; }
|
||||
inline void setAlgorithm(const Algorithm::Id id) { m_algorithm = id; }
|
||||
inline void setAlgorithm(const char *algo) { m_algorithm = algo; }
|
||||
inline void setClientId(const String &id) { m_clientId = id; }
|
||||
inline void setHeight(uint64_t height) { m_height = height; }
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
namespace xmrig {
|
||||
|
||||
static const char *kAlgo = "algo";
|
||||
static const char *kCoin = "coin";
|
||||
static const char *kDaemon = "daemon";
|
||||
static const char *kDaemonPollInterval = "daemon-poll-interval";
|
||||
static const char *kEnabled = "enabled";
|
||||
@@ -120,6 +121,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
|
||||
m_fingerprint = Json::getString(object, kFingerprint);
|
||||
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
|
||||
m_algorithm = Json::getString(object, kAlgo);
|
||||
m_coin = Json::getString(object, kCoin);
|
||||
|
||||
m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true));
|
||||
m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash));
|
||||
@@ -172,7 +174,7 @@ bool xmrig::Pool::isEnabled() const
|
||||
}
|
||||
# endif
|
||||
|
||||
if (isDaemon() && !algorithm().isValid()) {
|
||||
if (isDaemon() && (!algorithm().isValid() && !coin().isValid())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -186,6 +188,7 @@ bool xmrig::Pool::isEqual(const Pool &other) const
|
||||
&& m_keepAlive == other.m_keepAlive
|
||||
&& m_port == other.m_port
|
||||
&& m_algorithm == other.m_algorithm
|
||||
&& m_coin == other.m_coin
|
||||
&& m_fingerprint == other.m_fingerprint
|
||||
&& m_host == other.m_host
|
||||
&& m_password == other.m_password
|
||||
@@ -268,6 +271,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
|
||||
Value obj(kObjectType);
|
||||
|
||||
obj.AddMember(StringRef(kAlgo), m_algorithm.toJSON(), allocator);
|
||||
obj.AddMember(StringRef(kCoin), m_coin.toJSON(), allocator);
|
||||
obj.AddMember(StringRef(kUrl), m_url.toJSON(), allocator);
|
||||
obj.AddMember(StringRef(kUser), m_user.toJSON(), allocator);
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
|
||||
#include "base/tools/String.h"
|
||||
#include "crypto/common/Algorithm.h"
|
||||
#include "crypto/common/Coin.h"
|
||||
#include "rapidjson/fwd.h"
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ public:
|
||||
inline bool isTLS() const { return m_flags.test(FLAG_TLS); }
|
||||
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
|
||||
inline const Algorithm &algorithm() const { return m_algorithm; }
|
||||
inline const Coin &coin() const { return m_coin; }
|
||||
inline const String &fingerprint() const { return m_fingerprint; }
|
||||
inline const String &host() const { return m_host; }
|
||||
inline const String &password() const { return !m_password.isNull() ? m_password : kDefaultPassword; }
|
||||
@@ -107,6 +108,7 @@ private:
|
||||
bool parseIPv6(const char *addr);
|
||||
|
||||
Algorithm m_algorithm;
|
||||
Coin m_coin;
|
||||
int m_keepAlive;
|
||||
std::bitset<FLAG_MAX> m_flags;
|
||||
String m_fingerprint;
|
||||
|
||||
@@ -135,11 +135,12 @@ void xmrig::Pools::print() const
|
||||
{
|
||||
size_t i = 1;
|
||||
for (const Pool &pool : m_data) {
|
||||
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " algo " WHITE_BOLD("%s"),
|
||||
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " %s " WHITE_BOLD("%s"),
|
||||
i,
|
||||
(pool.isEnabled() ? (pool.isTLS() ? 32 : 36) : 31),
|
||||
pool.url().data(),
|
||||
pool.algorithm().isValid() ? pool.algorithm().shortName() : "auto"
|
||||
pool.coin().isValid() ? "coin" : "algo",
|
||||
pool.coin().isValid() ? pool.coin().name() : (pool.algorithm().isValid() ? pool.algorithm().shortName() : "auto")
|
||||
);
|
||||
|
||||
i++;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"huge-pages": true,
|
||||
"hw-aes": null,
|
||||
"priority": null,
|
||||
"max-threads-hint": 100,
|
||||
"asm": true,
|
||||
"argon2-impl": null,
|
||||
"cn/0": false,
|
||||
@@ -42,6 +43,7 @@
|
||||
"pools": [
|
||||
{
|
||||
"algo": null,
|
||||
"coin": null,
|
||||
"url": "donate.v2.xmrig.com:3333",
|
||||
"user": "YOUR_WALLET_ADDRESS",
|
||||
"pass": "x",
|
||||
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
bool isEnabled(const Algorithm &algorithm) const
|
||||
{
|
||||
for (IBackend *backend : backends) {
|
||||
if (backend->isEnabled(algorithm)) {
|
||||
if (backend->isEnabled() && backend->isEnabled(algorithm)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,9 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const
|
||||
return transformUint64(doc, key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10));
|
||||
}
|
||||
|
||||
case IConfig::CPUMaxThreadsKey: /* --cpu-max-threads-hint */
|
||||
return set(doc, kCpu, "max-threads-hint", static_cast<uint64_t>(strtol(arg, nullptr, 10)));
|
||||
|
||||
# ifdef XMRIG_FEATURE_ASM
|
||||
case IConfig::AssemblyKey: /* --asm */
|
||||
return set(doc, kCpu, "asm", arg);
|
||||
|
||||
@@ -57,6 +57,7 @@ R"===(
|
||||
"huge-pages": true,
|
||||
"hw-aes": null,
|
||||
"priority": null,
|
||||
"max-threads-hint": 100,
|
||||
"asm": true,
|
||||
"argon2-impl": null,
|
||||
"cn/0": false,
|
||||
@@ -76,6 +77,7 @@ R"===(
|
||||
"pools": [
|
||||
{
|
||||
"algo": null,
|
||||
"coin": null,
|
||||
"url": "donate.v2.xmrig.com:3333",
|
||||
"user": "YOUR_WALLET_ADDRESS",
|
||||
"pass": "x",
|
||||
|
||||
@@ -45,6 +45,7 @@ static const char short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:S";
|
||||
|
||||
static const option options[] = {
|
||||
{ "algo", 1, nullptr, IConfig::AlgorithmKey },
|
||||
{ "coin", 1, nullptr, IConfig::CoinKey },
|
||||
# ifdef XMRIG_FEATURE_HTTP
|
||||
{ "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey },
|
||||
{ "api-id", 1, nullptr, IConfig::ApiIdKey },
|
||||
@@ -81,6 +82,8 @@ static const option options[] = {
|
||||
{ "userpass", 1, nullptr, IConfig::UserpassKey },
|
||||
{ "rig-id", 1, nullptr, IConfig::RigIdKey },
|
||||
{ "no-cpu", 0, nullptr, IConfig::CPUKey },
|
||||
{ "max-cpu-usage", 1, nullptr, IConfig::CPUMaxThreadsKey },
|
||||
{ "cpu-max-threads-hint", 1, nullptr, IConfig::CPUMaxThreadsKey },
|
||||
# ifdef XMRIG_FEATURE_TLS
|
||||
{ "tls", 0, nullptr, IConfig::TlsKey },
|
||||
{ "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey },
|
||||
|
||||
@@ -76,6 +76,7 @@ static inline const std::string &usage()
|
||||
u += " -v, --av=N algorithm variation, 0 auto select\n";
|
||||
u += " --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n";
|
||||
u += " --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n";
|
||||
u += " --cpu-max-threads-hint=N maximum CPU threads count (in percentage) hint for autoconfig\n";
|
||||
u += " --no-huge-pages disable huge pages support\n";
|
||||
u += " --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer\n";
|
||||
|
||||
|
||||
@@ -103,9 +103,8 @@ static AlgoName const algorithm_names[] = {
|
||||
{ "cryptonight_turtle", "cn_turtle", Algorithm::CN_PICO_0 },
|
||||
# endif
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
{ "randomx/0", "rx/0", Algorithm::RX_0 },
|
||||
{ "randomx/test", "rx/test", Algorithm::RX_0 },
|
||||
{ "randomx/0", "rx/0", Algorithm::RX_0 },
|
||||
{ "randomx/0", "rx/0", Algorithm::RX_0 },
|
||||
{ "RandomX", "rx", Algorithm::RX_0 },
|
||||
{ "randomx/wow", "rx/wow", Algorithm::RX_WOW },
|
||||
{ "RandomWOW", nullptr, Algorithm::RX_WOW },
|
||||
|
||||
103
src/crypto/common/Coin.cpp
Normal file
103
src/crypto/common/Coin.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
|
||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "crypto/common/Coin.h"
|
||||
#include "rapidjson/document.h"
|
||||
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
struct CoinName
|
||||
{
|
||||
const char *name;
|
||||
const Coin::Id id;
|
||||
};
|
||||
|
||||
|
||||
static CoinName const coin_names[] = {
|
||||
{ "monero", Coin::MONERO },
|
||||
{ "xmr", Coin::MONERO },
|
||||
};
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
|
||||
xmrig::Algorithm::Id xmrig::Coin::algorithm(uint8_t blobVersion) const
|
||||
{
|
||||
if (id() == MONERO) {
|
||||
return (blobVersion >= 12) ? Algorithm::RX_0 : Algorithm::CN_R;
|
||||
}
|
||||
|
||||
return Algorithm::INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *xmrig::Coin::name() const
|
||||
{
|
||||
for (const auto &i : coin_names) {
|
||||
if (i.id == m_id) {
|
||||
return i.name;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
rapidjson::Value xmrig::Coin::toJSON() const
|
||||
{
|
||||
using namespace rapidjson;
|
||||
|
||||
return isValid() ? Value(StringRef(name())) : Value(kNullType);
|
||||
}
|
||||
|
||||
|
||||
xmrig::Coin::Id xmrig::Coin::parse(const char *name)
|
||||
{
|
||||
if (name == nullptr || strlen(name) < 3) {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
for (const auto &i : coin_names) {
|
||||
if (strcasecmp(name, i.name) == 0) {
|
||||
return i.id;
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID;
|
||||
}
|
||||
75
src/crypto/common/Coin.h
Normal file
75
src/crypto/common/Coin.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
|
||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef XMRIG_COIN_H
|
||||
#define XMRIG_COIN_H
|
||||
|
||||
|
||||
#include "crypto/common/Algorithm.h"
|
||||
#include "rapidjson/fwd.h"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
class Coin
|
||||
{
|
||||
public:
|
||||
enum Id : int {
|
||||
INVALID = -1,
|
||||
MONERO,
|
||||
};
|
||||
|
||||
|
||||
Coin() = default;
|
||||
inline Coin(const char *name) : m_id(parse(name)) {}
|
||||
inline Coin(Id id) : m_id(id) {}
|
||||
|
||||
|
||||
inline bool isEqual(const Coin &other) const { return m_id == other.m_id; }
|
||||
inline bool isValid() const { return m_id != INVALID; }
|
||||
inline Id id() const { return m_id; }
|
||||
|
||||
Algorithm::Id algorithm(uint8_t blobVersion) const;
|
||||
const char *name() const;
|
||||
rapidjson::Value toJSON() const;
|
||||
|
||||
inline bool operator!=(Coin::Id id) const { return m_id != id; }
|
||||
inline bool operator!=(const Coin &other) const { return !isEqual(other); }
|
||||
inline bool operator==(Coin::Id id) const { return m_id == id; }
|
||||
inline bool operator==(const Coin &other) const { return isEqual(other); }
|
||||
inline operator Coin::Id() const { return m_id; }
|
||||
|
||||
static Id parse(const char *name);
|
||||
|
||||
private:
|
||||
Id m_id = INVALID;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* XMRIG_COIN_H */
|
||||
@@ -47,6 +47,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
@@ -96,12 +97,14 @@ class RxPrivate
|
||||
public:
|
||||
XMRIG_DISABLE_COPY_MOVE(RxPrivate)
|
||||
|
||||
inline RxPrivate()
|
||||
inline RxPrivate() :
|
||||
m_counter(0),
|
||||
m_last(0)
|
||||
{
|
||||
m_async = new uv_async_t;
|
||||
m_async->data = this;
|
||||
|
||||
uv_async_init(uv_default_loop(), m_async, RxPrivate::onReady);
|
||||
uv_async_init(uv_default_loop(), m_async, [](uv_async_t *) { d_ptr->onReady(); });
|
||||
|
||||
# ifdef XMRIG_FEATURE_HWLOC
|
||||
if (Cpu::info()->nodes() > 1) {
|
||||
@@ -130,11 +133,12 @@ public:
|
||||
|
||||
|
||||
inline bool isNUMA() const { return m_numa; }
|
||||
inline bool isReady(const Job &job) const { return m_ready == count() && m_algorithm == job.algorithm() && m_seed == job.seed(); }
|
||||
inline const Algorithm &algorithm() const { return m_algorithm; }
|
||||
inline const Buffer &seed() const { return m_seed; }
|
||||
inline size_t count() const { return isNUMA() ? datasets.size() : 1; }
|
||||
inline void asyncSend() { m_ready++; if (m_ready == count()) { uv_async_send(m_async); } }
|
||||
|
||||
inline uint64_t counter() { return m_counter.load(std::memory_order_relaxed); }
|
||||
inline void asyncSend(uint64_t counter) { m_ready++; if (m_ready == count()) { m_last = counter; uv_async_send(m_async); } }
|
||||
|
||||
static void allocate(uint32_t nodeId)
|
||||
{
|
||||
@@ -176,14 +180,14 @@ public:
|
||||
}
|
||||
|
||||
|
||||
static void initDataset(uint32_t nodeId, uint32_t threads)
|
||||
static void initDataset(uint32_t nodeId, uint32_t threads, uint64_t counter)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
const uint64_t ts = Chrono::steadyMSecs();
|
||||
|
||||
d_ptr->getOrAllocate(nodeId)->init(d_ptr->seed(), threads);
|
||||
d_ptr->asyncSend();
|
||||
d_ptr->asyncSend(counter);
|
||||
|
||||
LOG_INFO("%s" CYAN_BOLD("#%u") GREEN(" init done ") CYAN_BOLD("%zu/%zu") BLACK_BOLD(" (%" PRIu64 " ms)"), tag, nodeId, d_ptr->m_ready, d_ptr->count(), Chrono::steadyMSecs() - ts);
|
||||
}
|
||||
@@ -222,32 +226,31 @@ public:
|
||||
m_hugePages = hugePages;
|
||||
m_listener = listener;
|
||||
m_seed = job.seed();
|
||||
}
|
||||
|
||||
|
||||
inline bool isReady(const Job &job)
|
||||
{
|
||||
return m_ready == count() && m_algorithm == job.algorithm() && m_seed == job.seed();
|
||||
++m_counter;
|
||||
}
|
||||
|
||||
|
||||
std::map<uint32_t, RxDataset *> datasets;
|
||||
|
||||
private:
|
||||
static void onReady(uv_async_t *)
|
||||
inline void onReady()
|
||||
{
|
||||
if (d_ptr->m_listener) {
|
||||
d_ptr->m_listener->onDatasetReady();
|
||||
if (m_listener && counter() == m_last.load(std::memory_order_relaxed)) {
|
||||
m_listener->onDatasetReady();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Algorithm m_algorithm;
|
||||
bool m_hugePages = true;
|
||||
bool m_numa = true;
|
||||
Buffer m_seed;
|
||||
IRxListener *m_listener = nullptr;
|
||||
size_t m_ready = 0;
|
||||
uv_async_t *m_async;
|
||||
std::atomic<uint64_t> m_counter;
|
||||
std::atomic<uint64_t> m_last;
|
||||
uv_async_t *m_async = nullptr;
|
||||
};
|
||||
|
||||
|
||||
@@ -269,6 +272,7 @@ bool xmrig::Rx::init(const Job &job, int initThreads, bool hugePages, bool numa,
|
||||
d_ptr->setState(job, hugePages, numa, listener);
|
||||
const uint32_t threads = initThreads < 1 ? static_cast<uint32_t>(Cpu::info()->threads()) : static_cast<uint32_t>(initThreads);
|
||||
const String buf = Buffer::toHex(job.seed().data(), 8);
|
||||
const uint64_t counter = d_ptr->counter();
|
||||
|
||||
LOG_INFO("%s" MAGENTA_BOLD("init dataset%s") " algo " WHITE_BOLD("%s (") CYAN_BOLD("%u") WHITE_BOLD(" threads)") BLACK_BOLD(" seed %s..."),
|
||||
tag,
|
||||
@@ -281,14 +285,14 @@ bool xmrig::Rx::init(const Job &job, int initThreads, bool hugePages, bool numa,
|
||||
# ifdef XMRIG_FEATURE_HWLOC
|
||||
if (d_ptr->isNUMA()) {
|
||||
for (auto const &item : d_ptr->datasets) {
|
||||
std::thread thread(RxPrivate::initDataset, item.first, threads);
|
||||
std::thread thread(RxPrivate::initDataset, item.first, threads, counter);
|
||||
thread.detach();
|
||||
}
|
||||
}
|
||||
else
|
||||
# endif
|
||||
{
|
||||
std::thread thread(RxPrivate::initDataset, 0, threads);
|
||||
std::thread thread(RxPrivate::initDataset, 0, threads, counter);
|
||||
thread.detach();
|
||||
}
|
||||
|
||||
@@ -311,7 +315,7 @@ xmrig::RxDataset *xmrig::Rx::dataset(const Job &job, uint32_t nodeId)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return d_ptr->datasets.at(d_ptr->isNUMA() ? nodeId : 0);
|
||||
return d_ptr->datasets.at(d_ptr->isNUMA() ? (d_ptr->datasets.count(nodeId) ? nodeId : HwlocCpuInfo::nodeIndexes().front()) : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -63,4 +63,4 @@ private:
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* XMRIG_RX_CACHE_H */
|
||||
#endif /* XMRIG_RX_VM_H */
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <inttypes.h>
|
||||
#include <cinttypes>
|
||||
#include <ctime>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#include "base/io/log/Log.h"
|
||||
@@ -83,11 +83,7 @@ xmrig::Network::~Network()
|
||||
JobResults::stop();
|
||||
|
||||
delete m_timer;
|
||||
|
||||
if (m_donate) {
|
||||
delete m_donate;
|
||||
}
|
||||
|
||||
delete m_strategy;
|
||||
}
|
||||
|
||||
@@ -304,8 +300,8 @@ void xmrig::Network::getResults(rapidjson::Value &reply, rapidjson::Document &do
|
||||
results.AddMember("hashes_total", m_state.total, allocator);
|
||||
|
||||
Value best(kArrayType);
|
||||
for (size_t i = 0; i < m_state.topDiff.size(); ++i) {
|
||||
best.PushBack(m_state.topDiff[i], allocator);
|
||||
for (uint64_t i : m_state.topDiff) {
|
||||
best.PushBack(i, allocator);
|
||||
}
|
||||
|
||||
results.AddMember("best", best, allocator);
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "base/kernel/interfaces/IBaseListener.h"
|
||||
#include "base/kernel/interfaces/IStrategyListener.h"
|
||||
#include "base/kernel/interfaces/ITimerListener.h"
|
||||
#include "base/tools/Object.h"
|
||||
#include "interfaces/IJobResultListener.h"
|
||||
#include "net/NetworkState.h"
|
||||
#include "rapidjson/fwd.h"
|
||||
@@ -49,6 +50,8 @@ class IStrategy;
|
||||
class Network : public IJobResultListener, public IStrategyListener, public IBaseListener, public ITimerListener, public IApiListener
|
||||
{
|
||||
public:
|
||||
XMRIG_DISABLE_COPY_MOVE_DEFAULT(Network)
|
||||
|
||||
Network(Controller *controller);
|
||||
~Network() override;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
|
||||
|
||||
@@ -58,17 +58,10 @@ static const char *kDonateHostTls = "donate.ssl.xmrig.com";
|
||||
|
||||
|
||||
xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener *listener) :
|
||||
m_tls(false),
|
||||
m_userId(),
|
||||
m_donateTime(static_cast<uint64_t>(controller->config()->pools().donateLevel()) * 60 * 1000),
|
||||
m_idleTime((100 - static_cast<uint64_t>(controller->config()->pools().donateLevel())) * 60 * 1000),
|
||||
m_controller(controller),
|
||||
m_proxy(nullptr),
|
||||
m_strategy(nullptr),
|
||||
m_listener(listener),
|
||||
m_state(STATE_NEW),
|
||||
m_now(0),
|
||||
m_timestamp(0)
|
||||
m_listener(listener)
|
||||
{
|
||||
uint8_t hash[200];
|
||||
|
||||
@@ -77,15 +70,15 @@ xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener
|
||||
Buffer::toHex(hash, 32, m_userId);
|
||||
|
||||
# ifdef XMRIG_FEATURE_TLS
|
||||
m_pools.push_back(Pool(kDonateHostTls, 443, m_userId, nullptr, 0, true, true));
|
||||
m_pools.emplace_back(kDonateHostTls, 443, m_userId, nullptr, 0, true, true);
|
||||
# endif
|
||||
m_pools.push_back(Pool(kDonateHost, 3333, m_userId, nullptr, 0, true));
|
||||
m_pools.emplace_back(kDonateHost, 3333, m_userId, nullptr, 0, true);
|
||||
|
||||
if (m_pools.size() > 1) {
|
||||
m_strategy = new FailoverStrategy(m_pools, 1, 2, this, true);
|
||||
m_strategy = new FailoverStrategy(m_pools, 10, 2, this, true);
|
||||
}
|
||||
else {
|
||||
m_strategy = new SinglePoolStrategy(m_pools.front(), 1, 2, this, true);
|
||||
m_strategy = new SinglePoolStrategy(m_pools.front(), 10, 2, this, true);
|
||||
}
|
||||
|
||||
m_timer = new Timer(this);
|
||||
@@ -223,6 +216,18 @@ void xmrig::DonateStrategy::onLoginSuccess(IClient *client)
|
||||
}
|
||||
|
||||
|
||||
void xmrig::DonateStrategy::onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok)
|
||||
{
|
||||
m_listener->onVerifyAlgorithm(this, client, algorithm, ok);
|
||||
}
|
||||
|
||||
|
||||
void xmrig::DonateStrategy::onVerifyAlgorithm(IStrategy *, const IClient *client, const Algorithm &algorithm, bool *ok)
|
||||
{
|
||||
m_listener->onVerifyAlgorithm(this, client, algorithm, ok);
|
||||
}
|
||||
|
||||
|
||||
void xmrig::DonateStrategy::onTimer(const Timer *)
|
||||
{
|
||||
setState(isActive() ? STATE_WAIT : STATE_CONNECT);
|
||||
@@ -246,7 +251,7 @@ xmrig::Client *xmrig::DonateStrategy::createProxy()
|
||||
Pool pool(client->ip(), client->pool().port(), m_userId, client->pool().password(), 0, true, client->isTLS());
|
||||
pool.setAlgo(client->pool().algorithm());
|
||||
|
||||
Client *proxy = new Client(-1, Platform::userAgent(), this);
|
||||
auto proxy = new Client(-1, Platform::userAgent(), this);
|
||||
proxy->setPool(pool);
|
||||
proxy->setQuiet(true);
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "base/kernel/interfaces/IStrategyListener.h"
|
||||
#include "base/kernel/interfaces/ITimerListener.h"
|
||||
#include "base/net/stratum/Pool.h"
|
||||
#include "base/tools/Object.h"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
@@ -47,6 +48,8 @@ class IStrategyListener;
|
||||
class DonateStrategy : public IStrategy, public IStrategyListener, public ITimerListener, public IClientListener
|
||||
{
|
||||
public:
|
||||
XMRIG_DISABLE_COPY_MOVE_DEFAULT(DonateStrategy)
|
||||
|
||||
DonateStrategy(Controller *controller, IStrategyListener *listener);
|
||||
~DonateStrategy() override;
|
||||
|
||||
@@ -57,8 +60,6 @@ protected:
|
||||
inline void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) override { setJob(client, job); }
|
||||
inline void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); }
|
||||
inline void onResultAccepted(IStrategy *, IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); }
|
||||
inline void onVerifyAlgorithm(const IClient *, const Algorithm &, bool *) override {}
|
||||
inline void onVerifyAlgorithm(IStrategy *, const IClient *, const Algorithm &, bool *) override {}
|
||||
inline void resume() override {}
|
||||
|
||||
int64_t submit(const JobResult &result) override;
|
||||
@@ -74,6 +75,8 @@ protected:
|
||||
void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override;
|
||||
void onLogin(IStrategy *strategy, IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override;
|
||||
void onLoginSuccess(IClient *client) override;
|
||||
void onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok) override;
|
||||
void onVerifyAlgorithm(IStrategy *strategy, const IClient *client, const Algorithm &algorithm, bool *ok) override;
|
||||
|
||||
void onTimer(const Timer *timer) override;
|
||||
|
||||
@@ -96,19 +99,19 @@ private:
|
||||
void setState(State state);
|
||||
|
||||
Algorithm m_algorithm;
|
||||
bool m_tls;
|
||||
char m_userId[65];
|
||||
bool m_tls = false;
|
||||
char m_userId[65] = { 0 };
|
||||
const uint64_t m_donateTime;
|
||||
const uint64_t m_idleTime;
|
||||
Controller *m_controller;
|
||||
IClient *m_proxy;
|
||||
IStrategy *m_strategy;
|
||||
IClient *m_proxy = nullptr;
|
||||
IStrategy *m_strategy = nullptr;
|
||||
IStrategyListener *m_listener;
|
||||
State m_state;
|
||||
State m_state = STATE_NEW;
|
||||
std::vector<Pool> m_pools;
|
||||
Timer *m_timer;
|
||||
uint64_t m_now;
|
||||
uint64_t m_timestamp;
|
||||
Timer *m_timer = nullptr;
|
||||
uint64_t m_now = 0;
|
||||
uint64_t m_timestamp = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -28,15 +28,15 @@
|
||||
#define APP_ID "xmrig"
|
||||
#define APP_NAME "XMRig"
|
||||
#define APP_DESC "XMRig miner"
|
||||
#define APP_VERSION "4.1.0-beta"
|
||||
#define APP_VERSION "4.2.1-beta"
|
||||
#define APP_DOMAIN "xmrig.com"
|
||||
#define APP_SITE "www.xmrig.com"
|
||||
#define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com"
|
||||
#define APP_KIND "miner"
|
||||
|
||||
#define APP_VER_MAJOR 4
|
||||
#define APP_VER_MINOR 1
|
||||
#define APP_VER_PATCH 0
|
||||
#define APP_VER_MINOR 2
|
||||
#define APP_VER_PATCH 1
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# if (_MSC_VER >= 1920)
|
||||
|
||||
Reference in New Issue
Block a user