mirror of
https://github.com/xmrig/xmrig.git
synced 2026-04-17 21:12:58 -04:00
Merge branch 'master' of https://github.com/oxyzenQ/xmrig into pr3764
This commit is contained in:
@@ -65,7 +65,7 @@ public:
|
||||
}
|
||||
}
|
||||
# else
|
||||
inline ~Thread() { m_thread.join(); delete m_worker; }
|
||||
inline ~Thread() { if (m_thread.joinable()) { m_thread.join(); } delete m_worker; }
|
||||
|
||||
inline void start(void *(*callback)(void *)) { m_thread = std::thread(callback, this); }
|
||||
# endif
|
||||
|
||||
@@ -706,7 +706,7 @@ __kernel void cn2(__global uint4 *Scratchpad, __global ulong *states, __global u
|
||||
}
|
||||
|
||||
# if (ALGO_FAMILY == FAMILY_CN_HEAVY)
|
||||
/* Also left over threads performe this loop.
|
||||
/* Also left over threads perform this loop.
|
||||
* The left over thread results will be ignored
|
||||
*/
|
||||
#pragma unroll 16
|
||||
@@ -1005,7 +1005,7 @@ __kernel void Groestl(__global ulong *states, __global uint *BranchBuf, __global
|
||||
ulong State[8] = { 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0x0001000000000000UL };
|
||||
ulong H[8], M[8];
|
||||
|
||||
// BUG: AMD driver 19.7.X crashs if this is written as loop
|
||||
// BUG: AMD driver 19.7.X crashes if this is written as loop
|
||||
// Thx AMD for so bad software
|
||||
{
|
||||
((ulong8 *)M)[0] = vload8(0, states);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#else
|
||||
# define STATIC
|
||||
/* taken from https://www.khronos.org/registry/OpenCL/extensions/amd/cl_amd_media_ops.txt
|
||||
* Build-in Function
|
||||
* Built-in Function
|
||||
* uintn amd_bitalign (uintn src0, uintn src1, uintn src2)
|
||||
* Description
|
||||
* dst.s0 = (uint) (((((long)src0.s0) << 32) | (long)src1.s0) >> (src2.s0 & 31))
|
||||
|
||||
@@ -77,7 +77,7 @@ void keccak_f800_round(uint32_t st[25], const int r)
|
||||
void keccak_f800(uint32_t* st)
|
||||
{
|
||||
// Complete all 22 rounds as a separate impl to
|
||||
// evaluate only first 8 words is wasteful of regsters
|
||||
// evaluate only first 8 words is wasteful of registers
|
||||
for (int r = 0; r < 22; r++) {
|
||||
keccak_f800_round(st, r);
|
||||
}
|
||||
@@ -181,7 +181,7 @@ __kernel void progpow_search(__global dag_t const* g_dag, __global uint* job_blo
|
||||
for (int i = 10; i < 25; i++)
|
||||
state[i] = ravencoin_rndc[i-10];
|
||||
|
||||
// Run intial keccak round
|
||||
// Run initial keccak round
|
||||
keccak_f800(state);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#define KECCAK_ROUNDS 24
|
||||
|
||||
|
||||
/* *************************** Public Inteface ************************ */
|
||||
/* *************************** Public Interface ************************ */
|
||||
|
||||
/* For Init or Reset call these: */
|
||||
sha3_return_t
|
||||
|
||||
@@ -210,7 +210,7 @@ void xmrig::NetworkState::printResults() const
|
||||
printHashes(m_accepted, m_hashes);
|
||||
printDiff(m_diff);
|
||||
|
||||
if (m_active && !m_latency.empty()) {
|
||||
if (m_active && m_latencyCount > 0) {
|
||||
printAvgTime(avgTime());
|
||||
}
|
||||
|
||||
@@ -298,13 +298,19 @@ void xmrig::NetworkState::onResultAccepted(IStrategy *strategy, IClient *client,
|
||||
|
||||
uint32_t xmrig::NetworkState::latency() const
|
||||
{
|
||||
const size_t calls = m_latency.size();
|
||||
const size_t calls = m_latencyCount;
|
||||
if (calls == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto v = m_latency;
|
||||
std::nth_element(v.begin(), v.begin() + calls / 2, v.end());
|
||||
std::array<uint16_t, kLatencyWindow> v;
|
||||
const size_t start = (m_latencyPos + kLatencyWindow - calls) % kLatencyWindow;
|
||||
|
||||
for (size_t i = 0; i < calls; ++i) {
|
||||
v[i] = m_latency[(start + i) % kLatencyWindow];
|
||||
}
|
||||
|
||||
std::nth_element(v.begin(), v.begin() + calls / 2, v.begin() + calls);
|
||||
|
||||
return v[calls / 2];
|
||||
}
|
||||
@@ -312,11 +318,11 @@ uint32_t xmrig::NetworkState::latency() const
|
||||
|
||||
uint64_t xmrig::NetworkState::avgTime() const
|
||||
{
|
||||
if (m_latency.empty()) {
|
||||
if (m_latencyCount == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return connectionTime() / m_latency.size();
|
||||
return connectionTime() / m_latencyCount;
|
||||
}
|
||||
|
||||
|
||||
@@ -342,7 +348,12 @@ void xmrig::NetworkState::add(const SubmitResult &result, const char *error)
|
||||
std::sort(m_topDiff.rbegin(), m_topDiff.rend());
|
||||
}
|
||||
|
||||
m_latency.push_back(result.elapsed > 0xFFFF ? 0xFFFF : static_cast<uint16_t>(result.elapsed));
|
||||
m_latency[m_latencyPos] = result.elapsed > 0xFFFF ? 0xFFFF : static_cast<uint16_t>(result.elapsed);
|
||||
m_latencyPos = (m_latencyPos + 1) % kLatencyWindow;
|
||||
|
||||
if (m_latencyCount < kLatencyWindow) {
|
||||
m_latencyCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -355,5 +366,6 @@ void xmrig::NetworkState::stop()
|
||||
m_fingerprint = nullptr;
|
||||
|
||||
m_failures++;
|
||||
m_latency.clear();
|
||||
m_latencyCount = 0;
|
||||
m_latencyPos = 0;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
@@ -60,6 +59,8 @@ protected:
|
||||
void onResultAccepted(IStrategy *strategy, IClient *client, const SubmitResult &result, const char *error) override;
|
||||
|
||||
private:
|
||||
constexpr static size_t kLatencyWindow = 1024;
|
||||
|
||||
uint32_t latency() const;
|
||||
uint64_t avgTime() const;
|
||||
uint64_t connectionTime() const;
|
||||
@@ -70,7 +71,9 @@ private:
|
||||
bool m_active = false;
|
||||
char m_pool[256]{};
|
||||
std::array<uint64_t, 10> m_topDiff { { } };
|
||||
std::vector<uint16_t> m_latency;
|
||||
std::array<uint16_t, kLatencyWindow> m_latency { { } };
|
||||
size_t m_latencyCount = 0;
|
||||
size_t m_latencyPos = 0;
|
||||
String m_fingerprint;
|
||||
String m_ip;
|
||||
String m_tls;
|
||||
|
||||
@@ -76,10 +76,12 @@ void xmrig::Controller::stop()
|
||||
{
|
||||
Base::stop();
|
||||
|
||||
m_network.reset();
|
||||
if (m_miner) {
|
||||
m_miner->stop();
|
||||
m_miner.reset();
|
||||
}
|
||||
|
||||
m_miner->stop();
|
||||
m_miner.reset();
|
||||
m_network.reset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -49,6 +49,15 @@ void xmrig::CnCtx::release(cryptonight_ctx **ctx, size_t count)
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
if (ctx[i] && ctx[i]->generated_code) {
|
||||
# ifdef XMRIG_OS_WIN
|
||||
VirtualMemory::freeLargePagesMemory(reinterpret_cast<void *>(ctx[i]->generated_code), 0);
|
||||
# else
|
||||
VirtualMemory::freeLargePagesMemory(reinterpret_cast<void *>(ctx[i]->generated_code), 0x4000);
|
||||
# endif
|
||||
ctx[i]->generated_code = nullptr;
|
||||
}
|
||||
|
||||
_mm_free(ctx[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ static HashReturn Init(hashState *state, int hashbitlen)
|
||||
/*initialize the initial hash value of JH*/
|
||||
state->hashbitlen = hashbitlen;
|
||||
|
||||
/*load the intital hash value into state*/
|
||||
/*load the initial hash value into state*/
|
||||
switch (hashbitlen)
|
||||
{
|
||||
case 224: memcpy(state->x,JH224_H0,128); break;
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
multiple of size / 8)
|
||||
|
||||
ptr_cast(x,size) casts a pointer to a pointer to a
|
||||
varaiable of length 'size' bits
|
||||
variable of length 'size' bits
|
||||
*/
|
||||
|
||||
#define ui_type(size) uint##size##_t
|
||||
|
||||
@@ -124,6 +124,7 @@ uint32_t xmrig::VirtualMemory::bindToNUMANode(int64_t)
|
||||
void xmrig::VirtualMemory::destroy()
|
||||
{
|
||||
delete pool;
|
||||
pool = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ void hashAes1Rx4(const void *input, size_t inputSize, void *hash)
|
||||
rx_vec_i128 state0, state1, state2, state3;
|
||||
rx_vec_i128 in0, in1, in2, in3;
|
||||
|
||||
//intial state
|
||||
//initial state
|
||||
state0 = rx_set_int_vec_i128(AES_HASH_1R_STATE0);
|
||||
state1 = rx_set_int_vec_i128(AES_HASH_1R_STATE1);
|
||||
state2 = rx_set_int_vec_i128(AES_HASH_1R_STATE2);
|
||||
|
||||
@@ -174,7 +174,7 @@ FORCE_INLINE void rx_set_rounding_mode(uint32_t mode) {
|
||||
_mm_setcsr(rx_mxcsr_default | (mode << 13));
|
||||
}
|
||||
|
||||
#elif defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__) //sadly only POWER7 and newer will be able to use SIMD acceleration. Earlier processors cant use doubles or 64 bit integers with SIMD
|
||||
#elif defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__) //sadly only POWER7 and newer will be able to use SIMD acceleration. Earlier processors can't use doubles or 64 bit integers with SIMD
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
|
||||
@@ -231,7 +231,7 @@ RANDOMX_EXPORT unsigned long randomx_dataset_item_count(void);
|
||||
*
|
||||
* @param dataset is a pointer to a previously allocated randomx_dataset structure. Must not be NULL.
|
||||
* @param cache is a pointer to a previously allocated and initialized randomx_cache structure. Must not be NULL.
|
||||
* @param startItem is the item number where intialization should start.
|
||||
* @param startItem is the item number where initialization should start.
|
||||
* @param itemCount is the number of items that should be initialized.
|
||||
*/
|
||||
RANDOMX_EXPORT void randomx_init_dataset(randomx_dataset *dataset, randomx_cache *cache, unsigned long startItem, unsigned long itemCount);
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
|
||||
|
||||
#include <cassert>
|
||||
#include <atomic>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -66,6 +67,9 @@ namespace xmrig {
|
||||
|
||||
|
||||
#if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
|
||||
class JobResultsPrivate;
|
||||
|
||||
|
||||
class JobBundle
|
||||
{
|
||||
public:
|
||||
@@ -86,14 +90,14 @@ public:
|
||||
class JobBaton : public Baton<uv_work_t>
|
||||
{
|
||||
public:
|
||||
inline JobBaton(std::list<JobBundle> &&bundles, IJobResultListener *listener, bool hwAES) :
|
||||
inline JobBaton(std::list<JobBundle> &&bundles, JobResultsPrivate *owner, bool hwAES) :
|
||||
hwAES(hwAES),
|
||||
listener(listener),
|
||||
owner(owner),
|
||||
bundles(std::move(bundles))
|
||||
{}
|
||||
|
||||
const bool hwAES;
|
||||
IJobResultListener *listener;
|
||||
JobResultsPrivate *owner;
|
||||
std::list<JobBundle> bundles;
|
||||
std::vector<JobResult> results;
|
||||
uint32_t errors = 0;
|
||||
@@ -188,6 +192,8 @@ static void getResults(JobBundle &bundle, std::vector<JobResult> &results, uint3
|
||||
|
||||
checkHash(bundle, results, nonce, hash, errors);
|
||||
}
|
||||
|
||||
CnCtx::release(ctx, 1);
|
||||
}
|
||||
|
||||
delete memory;
|
||||
@@ -200,6 +206,11 @@ class JobResultsPrivate : public IAsyncListener
|
||||
public:
|
||||
XMRIG_DISABLE_COPY_MOVE_DEFAULT(JobResultsPrivate)
|
||||
|
||||
constexpr static size_t kMaxQueuedResults = 4096;
|
||||
# if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
|
||||
constexpr static size_t kMaxQueuedBundles = 256;
|
||||
# endif
|
||||
|
||||
inline JobResultsPrivate(IJobResultListener *listener, bool hwAES) :
|
||||
m_hwAES(hwAES),
|
||||
m_listener(listener)
|
||||
@@ -214,9 +225,20 @@ public:
|
||||
inline void submit(const JobResult &result)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (m_stopping) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_results.size() >= kMaxQueuedResults) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_results.push_back(result);
|
||||
|
||||
m_async->send();
|
||||
if (m_async && !m_pendingAsync.exchange(true)) {
|
||||
m_async->send();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -224,13 +246,55 @@ public:
|
||||
inline void submit(const Job &job, uint32_t *results, size_t count, uint32_t device_index)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (count > 0xFF) {
|
||||
count = 0xFF;
|
||||
}
|
||||
|
||||
if (m_stopping) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_bundles.size() >= kMaxQueuedBundles) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_bundles.emplace_back(job, results, count, device_index);
|
||||
|
||||
m_async->send();
|
||||
if (m_async && !m_pendingAsync.exchange(true)) {
|
||||
m_async->send();
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
|
||||
inline void stop()
|
||||
{
|
||||
bool deleteNow = false;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_stopping = true;
|
||||
m_listener = nullptr;
|
||||
m_results.clear();
|
||||
|
||||
# if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
|
||||
m_bundles.clear();
|
||||
m_workScheduled = false;
|
||||
m_deleteWhenDone = true;
|
||||
deleteNow = (m_pendingWork == 0);
|
||||
# else
|
||||
deleteNow = true;
|
||||
# endif
|
||||
}
|
||||
|
||||
if (deleteNow) {
|
||||
m_async.reset();
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
inline void onAsync() override { submit(); }
|
||||
|
||||
@@ -239,23 +303,33 @@ private:
|
||||
# if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
|
||||
inline void submit()
|
||||
{
|
||||
m_pendingAsync.store(false);
|
||||
|
||||
std::list<JobBundle> bundles;
|
||||
std::list<JobResult> results;
|
||||
|
||||
m_mutex.lock();
|
||||
m_bundles.swap(bundles);
|
||||
m_results.swap(results);
|
||||
|
||||
const bool canScheduleWork = !m_workScheduled && !m_stopping && !m_bundles.empty();
|
||||
if (canScheduleWork) {
|
||||
m_bundles.swap(bundles);
|
||||
m_workScheduled = true;
|
||||
m_pendingWork++;
|
||||
}
|
||||
m_mutex.unlock();
|
||||
|
||||
for (const auto &result : results) {
|
||||
m_listener->onJobResult(result);
|
||||
if (m_listener) {
|
||||
m_listener->onJobResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
if (bundles.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto baton = new JobBaton(std::move(bundles), m_listener, m_hwAES);
|
||||
auto baton = new JobBaton(std::move(bundles), this, m_hwAES);
|
||||
|
||||
uv_queue_work(uv_default_loop(), &baton->req,
|
||||
[](uv_work_t *req) {
|
||||
@@ -268,8 +342,67 @@ private:
|
||||
[](uv_work_t *req, int) {
|
||||
auto baton = static_cast<JobBaton*>(req->data);
|
||||
|
||||
for (const auto &result : baton->results) {
|
||||
baton->listener->onJobResult(result);
|
||||
if (baton->owner) {
|
||||
baton->owner->onBatonDone(std::move(baton->results));
|
||||
}
|
||||
|
||||
delete baton;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline void onBatonDone(std::vector<JobResult> &&results)
|
||||
{
|
||||
for (const auto &result : results) {
|
||||
if (m_listener) {
|
||||
m_listener->onJobResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
std::list<JobBundle> bundles;
|
||||
|
||||
m_mutex.lock();
|
||||
|
||||
m_pendingWork--;
|
||||
|
||||
const bool canScheduleWork = !m_stopping && !m_bundles.empty();
|
||||
if (canScheduleWork) {
|
||||
m_bundles.swap(bundles);
|
||||
m_pendingWork++;
|
||||
}
|
||||
else {
|
||||
m_workScheduled = false;
|
||||
}
|
||||
|
||||
const bool canDelete = m_deleteWhenDone && m_pendingWork == 0;
|
||||
m_mutex.unlock();
|
||||
|
||||
if (canDelete) {
|
||||
m_async.reset();
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
if (bundles.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto baton = new JobBaton(std::move(bundles), this, m_hwAES);
|
||||
|
||||
uv_queue_work(uv_default_loop(), &baton->req,
|
||||
[](uv_work_t *req) {
|
||||
auto baton = static_cast<JobBaton*>(req->data);
|
||||
|
||||
for (JobBundle &bundle : baton->bundles) {
|
||||
getResults(bundle, baton->results, baton->errors, baton->hwAES);
|
||||
}
|
||||
},
|
||||
[](uv_work_t *req, int) {
|
||||
auto baton = static_cast<JobBaton*>(req->data);
|
||||
|
||||
if (baton->owner) {
|
||||
baton->owner->onBatonDone(std::move(baton->results));
|
||||
}
|
||||
|
||||
delete baton;
|
||||
@@ -279,6 +412,8 @@ private:
|
||||
# else
|
||||
inline void submit()
|
||||
{
|
||||
m_pendingAsync.store(false);
|
||||
|
||||
std::list<JobResult> results;
|
||||
|
||||
m_mutex.lock();
|
||||
@@ -286,7 +421,9 @@ private:
|
||||
m_mutex.unlock();
|
||||
|
||||
for (const auto &result : results) {
|
||||
m_listener->onJobResult(result);
|
||||
if (m_listener) {
|
||||
m_listener->onJobResult(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
@@ -296,9 +433,14 @@ private:
|
||||
std::list<JobResult> m_results;
|
||||
std::mutex m_mutex;
|
||||
std::shared_ptr<Async> m_async;
|
||||
std::atomic<bool> m_pendingAsync{ false };
|
||||
bool m_stopping = false;
|
||||
|
||||
# if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
|
||||
std::list<JobBundle> m_bundles;
|
||||
bool m_workScheduled = false;
|
||||
uint32_t m_pendingWork = 0;
|
||||
bool m_deleteWhenDone = false;
|
||||
# endif
|
||||
};
|
||||
|
||||
@@ -325,11 +467,12 @@ void xmrig::JobResults::setListener(IJobResultListener *listener, bool hwAES)
|
||||
|
||||
void xmrig::JobResults::stop()
|
||||
{
|
||||
assert(handler != nullptr);
|
||||
|
||||
delete handler;
|
||||
|
||||
auto h = handler;
|
||||
handler = nullptr;
|
||||
|
||||
if (h) {
|
||||
h->stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -347,8 +490,6 @@ void xmrig::JobResults::submit(const Job& job, uint32_t nonce, const uint8_t* re
|
||||
|
||||
void xmrig::JobResults::submit(const JobResult &result)
|
||||
{
|
||||
assert(handler != nullptr);
|
||||
|
||||
if (handler) {
|
||||
handler->submit(result);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user