Merge pull request #3569 from SChernykh/dev

Fix: don't use NaN in hashrate calculations
This commit is contained in:
xmrig 2024-10-23 17:18:36 +07:00 committed by GitHub
commit 8b03750806
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 105 additions and 56 deletions

View file

@ -30,10 +30,10 @@
#include "base/tools/Handle.h" #include "base/tools/Handle.h"
inline static const char *format(double h, char *buf, size_t size) inline static const char *format(std::pair<bool, double> h, char *buf, size_t size)
{ {
if (std::isnormal(h)) { if (h.first) {
snprintf(buf, size, (h < 100.0) ? "%04.2f" : "%03.1f", h); snprintf(buf, size, (h.second < 100.0) ? "%04.2f" : "%03.1f", h.second);
return buf; return buf;
} }
@ -80,15 +80,16 @@ double xmrig::Hashrate::average() const
} }
const char *xmrig::Hashrate::format(double h, char *buf, size_t size) const char *xmrig::Hashrate::format(std::pair<bool, double> h, char *buf, size_t size)
{ {
return ::format(h, buf, size); return ::format(h, buf, size);
} }
rapidjson::Value xmrig::Hashrate::normalize(double d) rapidjson::Value xmrig::Hashrate::normalize(std::pair<bool, double> d)
{ {
return Json::normalize(d, false); using namespace rapidjson;
return d.first ? Value(floor(d.second * 100.0) / 100.0) : Value(kNullType);
} }
@ -122,11 +123,11 @@ rapidjson::Value xmrig::Hashrate::toJSON(size_t threadId, rapidjson::Document &d
#endif #endif
double xmrig::Hashrate::hashrate(size_t index, size_t ms) const std::pair<bool, double> xmrig::Hashrate::hashrate(size_t index, size_t ms) const
{ {
assert(index < m_threads); assert(index < m_threads);
if (index >= m_threads) { if (index >= m_threads) {
return nan(""); return { false, 0.0 };
} }
uint64_t earliestHashCount = 0; uint64_t earliestHashCount = 0;
@ -157,17 +158,27 @@ double xmrig::Hashrate::hashrate(size_t index, size_t ms) const
} while (idx != idx_start); } while (idx != idx_start);
if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) { if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) {
return nan(""); return { false, 0.0 };
} }
if (lastestStamp - earliestStamp == 0) { if (lastestHashCnt == earliestHashCount) {
return nan(""); return { true, 0.0 };
}
if (lastestStamp == earliestStamp) {
return { false, 0.0 };
} }
const auto hashes = static_cast<double>(lastestHashCnt - earliestHashCount); const auto hashes = static_cast<double>(lastestHashCnt - earliestHashCount);
const auto time = static_cast<double>(lastestStamp - earliestStamp) / 1000.0; const auto time = static_cast<double>(lastestStamp - earliestStamp);
return hashes / time; const auto hr = hashes * 1000.0 / time;
if (!std::isnormal(hr)) {
return { false, 0.0 };
}
return { true, hr };
} }

View file

@ -47,16 +47,16 @@ public:
Hashrate(size_t threads); Hashrate(size_t threads);
~Hashrate(); ~Hashrate();
inline double calc(size_t ms) const { const double data = hashrate(0U, ms); return std::isnormal(data) ? data : 0.0; } inline std::pair<bool, double> calc(size_t ms) const { return hashrate(0U, ms); }
inline double calc(size_t threadId, size_t ms) const { return hashrate(threadId + 1, ms); } inline std::pair<bool, double> calc(size_t threadId, size_t ms) const { return hashrate(threadId + 1, ms); }
inline size_t threads() const { return m_threads > 0U ? m_threads - 1U : 0U; } inline size_t threads() const { return m_threads > 0U ? m_threads - 1U : 0U; }
inline void add(size_t threadId, uint64_t count, uint64_t timestamp) { addData(threadId + 1U, count, timestamp); } inline void add(size_t threadId, uint64_t count, uint64_t timestamp) { addData(threadId + 1U, count, timestamp); }
inline void add(uint64_t count, uint64_t timestamp) { addData(0U, count, timestamp); } inline void add(uint64_t count, uint64_t timestamp) { addData(0U, count, timestamp); }
double average() const; double average() const;
static const char *format(double h, char *buf, size_t size); static const char *format(std::pair<bool, double> h, char *buf, size_t size);
static rapidjson::Value normalize(double d); static rapidjson::Value normalize(std::pair<bool, double> d);
# ifdef XMRIG_FEATURE_API # ifdef XMRIG_FEATURE_API
rapidjson::Value toJSON(rapidjson::Document &doc) const; rapidjson::Value toJSON(rapidjson::Document &doc) const;
@ -64,7 +64,7 @@ public:
# endif # endif
private: private:
double hashrate(size_t index, size_t ms) const; std::pair<bool, double> hashrate(size_t index, size_t ms) const;
void addData(size_t index, uint64_t count, uint64_t timestamp); void addData(size_t index, uint64_t count, uint64_t timestamp);
constexpr static size_t kBucketSize = 2 << 11; constexpr static size_t kBucketSize = 2 << 11;

View file

@ -372,15 +372,20 @@ void xmrig::CudaBackend::printHashrate(bool details)
char num[16 * 3] = { 0 }; char num[16 * 3] = { 0 };
const double hashrate_short = hashrate()->calc(Hashrate::ShortInterval); auto hashrate_short = hashrate()->calc(Hashrate::ShortInterval);
const double hashrate_medium = hashrate()->calc(Hashrate::MediumInterval); auto hashrate_medium = hashrate()->calc(Hashrate::MediumInterval);
const double hashrate_large = hashrate()->calc(Hashrate::LargeInterval); auto hashrate_large = hashrate()->calc(Hashrate::LargeInterval);
double scale = 1.0; double scale = 1.0;
const char* h = " H/s"; const char* h = " H/s";
if ((hashrate_short >= 1e6) || (hashrate_medium >= 1e6) || (hashrate_large >= 1e6)) { if ((hashrate_short.second >= 1e6) || (hashrate_medium.second >= 1e6) || (hashrate_large.second >= 1e6)) {
scale = 1e-6; scale = 1e-6;
hashrate_short.second *= scale;
hashrate_medium.second *= scale;
hashrate_large.second *= scale;
h = "MH/s"; h = "MH/s";
} }
@ -388,12 +393,20 @@ void xmrig::CudaBackend::printHashrate(bool details)
size_t i = 0; size_t i = 0;
for (const auto& data : d_ptr->threads) { for (const auto& data : d_ptr->threads) {
auto h0 = hashrate()->calc(i, Hashrate::ShortInterval);
auto h1 = hashrate()->calc(i, Hashrate::MediumInterval);
auto h2 = hashrate()->calc(i, Hashrate::LargeInterval);
h0.second *= scale;
h1.second *= scale;
h2.second *= scale;
Log::print("| %8zu | %8" PRId64 " | %8s | %8s | %8s |" CYAN_BOLD(" #%u") YELLOW(" %s") GREEN(" %s"), Log::print("| %8zu | %8" PRId64 " | %8s | %8s | %8s |" CYAN_BOLD(" #%u") YELLOW(" %s") GREEN(" %s"),
i, i,
data.thread.affinity(), data.thread.affinity(),
Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval) * scale, num, sizeof num / 3), Hashrate::format(h0, num, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval) * scale, num + 16, sizeof num / 3), Hashrate::format(h1, num + 16, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval) * scale, num + 16 * 2, sizeof num / 3), Hashrate::format(h2, num + 16 * 2, sizeof num / 3),
data.device.index(), data.device.index(),
data.device.topology().toString().data(), data.device.topology().toString().data(),
data.device.name().data() data.device.name().data()
@ -403,9 +416,9 @@ void xmrig::CudaBackend::printHashrate(bool details)
} }
Log::print(WHITE_BOLD_S "| - | - | %8s | %8s | %8s |", Log::print(WHITE_BOLD_S "| - | - | %8s | %8s | %8s |",
Hashrate::format(hashrate_short * scale, num, sizeof num / 3), Hashrate::format(hashrate_short , num, sizeof num / 3),
Hashrate::format(hashrate_medium * scale, num + 16, sizeof num / 3), Hashrate::format(hashrate_medium, num + 16, sizeof num / 3),
Hashrate::format(hashrate_large * scale, num + 16 * 2, sizeof num / 3) Hashrate::format(hashrate_large , num + 16 * 2, sizeof num / 3)
); );
} }

View file

@ -352,15 +352,20 @@ void xmrig::OclBackend::printHashrate(bool details)
char num[16 * 3] = { 0 }; char num[16 * 3] = { 0 };
const double hashrate_short = hashrate()->calc(Hashrate::ShortInterval); auto hashrate_short = hashrate()->calc(Hashrate::ShortInterval);
const double hashrate_medium = hashrate()->calc(Hashrate::MediumInterval); auto hashrate_medium = hashrate()->calc(Hashrate::MediumInterval);
const double hashrate_large = hashrate()->calc(Hashrate::LargeInterval); auto hashrate_large = hashrate()->calc(Hashrate::LargeInterval);
double scale = 1.0; double scale = 1.0;
const char* h = " H/s"; const char* h = " H/s";
if ((hashrate_short >= 1e6) || (hashrate_medium >= 1e6) || (hashrate_large >= 1e6)) { if ((hashrate_short.second >= 1e6) || (hashrate_medium.second >= 1e6) || (hashrate_large.second >= 1e6)) {
scale = 1e-6; scale = 1e-6;
hashrate_short.second *= scale;
hashrate_medium.second *= scale;
hashrate_large.second *= scale;
h = "MH/s"; h = "MH/s";
} }
@ -368,12 +373,16 @@ void xmrig::OclBackend::printHashrate(bool details)
size_t i = 0; size_t i = 0;
for (const auto& data : d_ptr->threads) { for (const auto& data : d_ptr->threads) {
auto h0 = hashrate()->calc(i, Hashrate::ShortInterval);
auto h1 = hashrate()->calc(i, Hashrate::MediumInterval);
auto h2 = hashrate()->calc(i, Hashrate::LargeInterval);
Log::print("| %8zu | %8" PRId64 " | %8s | %8s | %8s |" CYAN_BOLD(" #%u") YELLOW(" %s") " %s", Log::print("| %8zu | %8" PRId64 " | %8s | %8s | %8s |" CYAN_BOLD(" #%u") YELLOW(" %s") " %s",
i, i,
data.affinity, data.affinity,
Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval) * scale, num, sizeof num / 3), Hashrate::format(h0, num, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval) * scale, num + 16, sizeof num / 3), Hashrate::format(h1, num + 16, sizeof num / 3),
Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval) * scale, num + 16 * 2, sizeof num / 3), Hashrate::format(h2, num + 16 * 2, sizeof num / 3),
data.device.index(), data.device.index(),
data.device.topology().toString().data(), data.device.topology().toString().data(),
data.device.printableName().data() data.device.printableName().data()
@ -383,9 +392,9 @@ void xmrig::OclBackend::printHashrate(bool details)
} }
Log::print(WHITE_BOLD_S "| - | - | %8s | %8s | %8s |", Log::print(WHITE_BOLD_S "| - | - | %8s | %8s | %8s |",
Hashrate::format(hashrate_short * scale, num, sizeof num / 3), Hashrate::format(hashrate_short , num, sizeof num / 3),
Hashrate::format(hashrate_medium * scale, num + 16, sizeof num / 3), Hashrate::format(hashrate_medium, num + 16, sizeof num / 3),
Hashrate::format(hashrate_large * scale, num + 16 * 2, sizeof num / 3) Hashrate::format(hashrate_large , num + 16 * 2, sizeof num / 3)
); );
} }

View file

@ -173,7 +173,7 @@ public:
Value total(kArrayType); Value total(kArrayType);
Value threads(kArrayType); Value threads(kArrayType);
double t[3] = { 0.0 }; std::pair<bool, double> t[3] = { { true, 0.0 }, { true, 0.0 }, { true, 0.0 } };
for (IBackend *backend : backends) { for (IBackend *backend : backends) {
const Hashrate *hr = backend->hashrate(); const Hashrate *hr = backend->hashrate();
@ -181,9 +181,13 @@ public:
continue; continue;
} }
t[0] += hr->calc(Hashrate::ShortInterval); const auto h0 = hr->calc(Hashrate::ShortInterval);
t[1] += hr->calc(Hashrate::MediumInterval); const auto h1 = hr->calc(Hashrate::MediumInterval);
t[2] += hr->calc(Hashrate::LargeInterval); const auto h2 = hr->calc(Hashrate::LargeInterval);
if (h0.first) { t[0].second += h0.second; } else { t[0].first = false; }
if (h1.first) { t[1].second += h1.second; } else { t[1].first = false; }
if (h2.first) { t[2].second += h2.second; } else { t[2].first = false; }
if (version > 1) { if (version > 1) {
continue; continue;
@ -204,7 +208,7 @@ public:
total.PushBack(Hashrate::normalize(t[2]), allocator); total.PushBack(Hashrate::normalize(t[2]), allocator);
hashrate.AddMember("total", total, allocator); hashrate.AddMember("total", total, allocator);
hashrate.AddMember("highest", Hashrate::normalize(maxHashrate[algorithm]), allocator); hashrate.AddMember("highest", Hashrate::normalize({ maxHashrate[algorithm] > 0.0, maxHashrate[algorithm] }), allocator);
if (version == 1) { if (version == 1) {
hashrate.AddMember("threads", threads, allocator); hashrate.AddMember("threads", threads, allocator);
@ -283,7 +287,7 @@ public:
void printHashrate(bool details) void printHashrate(bool details)
{ {
char num[16 * 5] = { 0 }; char num[16 * 5] = { 0 };
double speed[3] = { 0.0 }; std::pair<bool, double> speed[3] = { { true, 0.0 }, { true, 0.0 }, { true, 0.0 } };
uint32_t count = 0; uint32_t count = 0;
double avg_hashrate = 0.0; double avg_hashrate = 0.0;
@ -293,9 +297,13 @@ public:
if (hashrate) { if (hashrate) {
++count; ++count;
speed[0] += hashrate->calc(Hashrate::ShortInterval); const auto h0 = hashrate->calc(Hashrate::ShortInterval);
speed[1] += hashrate->calc(Hashrate::MediumInterval); const auto h1 = hashrate->calc(Hashrate::MediumInterval);
speed[2] += hashrate->calc(Hashrate::LargeInterval); const auto h2 = hashrate->calc(Hashrate::LargeInterval);
if (h0.first) { speed[0].second += h0.second; } else { speed[0].first = false; }
if (h1.first) { speed[1].second += h1.second; } else { speed[1].first = false; }
if (h2.first) { speed[2].second += h2.second; } else { speed[2].first = false; }
avg_hashrate += hashrate->average(); avg_hashrate += hashrate->average();
} }
@ -312,8 +320,13 @@ public:
double scale = 1.0; double scale = 1.0;
const char* h = "H/s"; const char* h = "H/s";
if ((speed[0] >= 1e6) || (speed[1] >= 1e6) || (speed[2] >= 1e6) || (maxHashrate[algorithm] >= 1e6)) { if ((speed[0].second >= 1e6) || (speed[1].second >= 1e6) || (speed[2].second >= 1e6) || (maxHashrate[algorithm] >= 1e6)) {
scale = 1e-6; scale = 1e-6;
speed[0].second *= scale;
speed[1].second *= scale;
speed[2].second *= scale;
h = "MH/s"; h = "MH/s";
} }
@ -322,16 +335,16 @@ public:
# ifdef XMRIG_ALGO_GHOSTRIDER # ifdef XMRIG_ALGO_GHOSTRIDER
if (algorithm.family() == Algorithm::GHOSTRIDER) { if (algorithm.family() == Algorithm::GHOSTRIDER) {
snprintf(avg_hashrate_buf, sizeof(avg_hashrate_buf), " avg " CYAN_BOLD("%s %s"), Hashrate::format(avg_hashrate * scale, num + 16 * 4, 16), h); snprintf(avg_hashrate_buf, sizeof(avg_hashrate_buf), " avg " CYAN_BOLD("%s %s"), Hashrate::format({ true, avg_hashrate * scale }, num + 16 * 4, 16), h);
} }
# endif # endif
LOG_INFO("%s " WHITE_BOLD("speed") " 10s/60s/15m " CYAN_BOLD("%s") CYAN(" %s %s ") CYAN_BOLD("%s") " max " CYAN_BOLD("%s %s") "%s", LOG_INFO("%s " WHITE_BOLD("speed") " 10s/60s/15m " CYAN_BOLD("%s") CYAN(" %s %s ") CYAN_BOLD("%s") " max " CYAN_BOLD("%s %s") "%s",
Tags::miner(), Tags::miner(),
Hashrate::format(speed[0] * scale, num, 16), Hashrate::format(speed[0], num, 16),
Hashrate::format(speed[1] * scale, num + 16, 16), Hashrate::format(speed[1], num + 16, 16),
Hashrate::format(speed[2] * scale, num + 16 * 2, 16), h, Hashrate::format(speed[2], num + 16 * 2, 16), h,
Hashrate::format(maxHashrate[algorithm] * scale, num + 16 * 3, 16), h, Hashrate::format({ maxHashrate[algorithm] > 0.0, maxHashrate[algorithm] * scale }, num + 16 * 3, 16), h,
avg_hashrate_buf avg_hashrate_buf
); );
@ -646,7 +659,10 @@ void xmrig::Miner::onTimer(const Timer *)
} }
if (backend->hashrate()) { if (backend->hashrate()) {
maxHashrate += backend->hashrate()->calc(Hashrate::ShortInterval); const auto h = backend->hashrate()->calc(Hashrate::ShortInterval);
if (h.first) {
maxHashrate += h.second;
}
} }
} }