AVX2 optimized code for AstroBWT

Added "astrobwt-avx2" parameter in config.json, it's turned off ("false") by default.

4-5% speedup on CPUs with proper AVX2 support (AMD Ryzen starting with Zen2, Intel Core starting with Haswell).

There will be no speedup on the following CPUs:

- Intel Pentium/Celeron don't support AVX2
- AMD Zen/Zen+ have only half-speed AVX

GCC compiled version is faster without AVX2, MSVC compiled version is faster with AVX2
This commit is contained in:
SChernykh 2020-03-10 22:03:16 +01:00
parent 8698b73036
commit e22f798085
14 changed files with 563 additions and 15 deletions

View file

@ -52,6 +52,7 @@ static const char *kArgon2Impl = "argon2-impl";
#ifdef XMRIG_ALGO_ASTROBWT
static const char* kAstroBWTMaxSize = "astrobwt-max-size";
static const char* kAstroBWTAVX2 = "astrobwt-avx2";
#endif
@ -94,6 +95,7 @@ rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const
# ifdef XMRIG_ALGO_ASTROBWT
obj.AddMember(StringRef(kAstroBWTMaxSize), m_astrobwtMaxSize, allocator);
obj.AddMember(StringRef(kAstroBWTAVX2), m_astrobwtAVX2, allocator);
# endif
m_threads.toJSON(obj, doc);
@ -148,12 +150,20 @@ void xmrig::CpuConfig::read(const rapidjson::Value &value)
# endif
# ifdef XMRIG_ALGO_ASTROBWT
const auto& obj = Json::getValue(value, kAstroBWTMaxSize);
if (obj.IsNull() || !obj.IsInt()) {
const auto& astroBWTMaxSize = Json::getValue(value, kAstroBWTMaxSize);
if (astroBWTMaxSize.IsNull() || !astroBWTMaxSize.IsInt()) {
m_shouldSave = true;
}
else {
m_astrobwtMaxSize = std::min(std::max(obj.GetInt(), 400), 1200);
m_astrobwtMaxSize = std::min(std::max(astroBWTMaxSize.GetInt(), 400), 1200);
}
const auto& astroBWTAVX2 = Json::getValue(value, kAstroBWTAVX2);
if (astroBWTAVX2.IsNull() || !astroBWTAVX2.IsBool()) {
m_shouldSave = true;
}
else {
m_astrobwtAVX2 = astroBWTAVX2.GetBool();
}
# endif

View file

@ -60,6 +60,7 @@ public:
inline const String &argon2Impl() const { return m_argon2Impl; }
inline const Threads<CpuThreads> &threads() const { return m_threads; }
inline int astrobwtMaxSize() const { return m_astrobwtMaxSize; }
inline bool astrobwtAVX2() const { return m_astrobwtAVX2; }
inline int priority() const { return m_priority; }
inline uint32_t limit() const { return m_limit; }
@ -77,6 +78,7 @@ private:
bool m_shouldSave = false;
bool m_yield = true;
int m_astrobwtMaxSize = 550;
bool m_astrobwtAVX2 = false;
int m_memoryPool = 0;
int m_priority = -1;
String m_argon2Impl;

View file

@ -39,6 +39,7 @@ xmrig::CpuLaunchData::CpuLaunchData(const Miner *miner, const Algorithm &algorit
hwAES(config.isHwAES()),
yield(config.isYield()),
astrobwtMaxSize(config.astrobwtMaxSize()),
astrobwtAVX2(config.astrobwtAVX2()),
priority(config.priority()),
affinity(thread.affinity()),
miner(miner),

View file

@ -62,6 +62,7 @@ public:
const bool hwAES;
const bool yield;
const int astrobwtMaxSize;
const bool astrobwtAVX2;
const int priority;
const int64_t affinity;
const Miner *miner;

View file

@ -81,6 +81,7 @@ xmrig::CpuWorker<N>::CpuWorker(size_t id, const CpuLaunchData &data) :
m_yield(data.yield),
m_av(data.av()),
m_astrobwtMaxSize(data.astrobwtMaxSize * 1000),
m_astrobwtAVX2(data.astrobwtAVX2),
m_miner(data.miner),
m_ctx()
{
@ -262,7 +263,7 @@ void xmrig::CpuWorker<N>::start()
{
# ifdef XMRIG_ALGO_ASTROBWT
if (job.algorithm().family() == Algorithm::ASTROBWT) {
if (!astrobwt::astrobwt_dero(m_job.blob(), job.size(), m_ctx[0]->memory, m_hash, m_astrobwtMaxSize))
if (!astrobwt::astrobwt_dero(m_job.blob(), job.size(), m_ctx[0]->memory, m_hash, m_astrobwtMaxSize, m_astrobwtAVX2))
valid = false;
}
else

View file

@ -74,6 +74,7 @@ private:
const bool m_yield;
const CnHash::AlgoVariant m_av;
const int m_astrobwtMaxSize;
const bool m_astrobwtAVX2;
const Miner *m_miner;
cryptonight_ctx *m_ctx[N];
uint8_t m_hash[N * 32]{ 0 };