难度校验算法优化

背景

https://github.com/starcoinorg/starcoin/pull/3056 jolestar 的amd ryzen cpu 校验不通过,发现这个算法是使用C++实现

然后rust使用ffi调用的

https://github.com/starcoinorg/starcoin/blob/v1.9.0/consensus/cryptonight-rs/ext/variant2_int_sqrt.h#L9

 

__m128d x = _mm_castsi128_pd(_mm_add_epi64(_mm_cvtsi64_si128(sqrt_input >> 12), exp_double_bias)); \

发现使用了sse2指令但是编译 build.rs只有-maes,并没有sse2指令

感觉这个应该可以使用sse2指令对其进行加速,尝试看有没有成熟的实现对其进行加速,实在没有再尝试自己去实现

找库

xmrig

找到一个实现

https://github.com/xmrig/xmrig/blob/master/src/crypto/cn/CnHash.cpp#L323 看起来这就是我要找的实现

xmrig::CnHash::CnHash() { ADD_FN(Algorithm::CN_0); ADD_FN(Algorithm::CN_1); ADD_FN(Algorithm::CN_2); ADD_FN(Algorithm::CN_R); ADD_FN(Algorithm::CN_FAST); ADD_FN(Algorithm::CN_HALF); ADD_FN(Algorithm::CN_XAO); ADD_FN(Algorithm::CN_RTO); ADD_FN(Algorithm::CN_RWZ); ADD_FN(Algorithm::CN_ZLS); ADD_FN(Algorithm::CN_DOUBLE); ADD_FN_ASM(Algorithm::CN_2); ADD_FN_ASM(Algorithm::CN_HALF); ADD_FN_ASM(Algorithm::CN_R); ADD_FN_ASM(Algorithm::CN_RWZ); ADD_FN_ASM(Algorithm::CN_ZLS); ADD_FN_ASM(Algorithm::CN_DOUBLE);

看第6行和17行这个实现有C++还有ASM实现,果然还是直接使用汇编性能最好,感觉和rust crypto hash sha2实现一个套路

再看下ADD_FN

 

#define ADD_FN(algo) do { \ m_map[algo] = new cn_hash_fun_array{}; \ m_map[algo]->data[AV_SINGLE][Assembly::NONE] = cryptonight_single_hash<algo, false, 0>; \ m_map[algo]->data[AV_SINGLE_SOFT][Assembly::NONE] = cryptonight_single_hash<algo, true, 0>; \ m_map[algo]->data[AV_DOUBLE][Assembly::NONE] = cryptonight_double_hash<algo, false>; \ m_map[algo]->data[AV_DOUBLE_SOFT][Assembly::NONE] = cryptonight_double_hash<algo, true>; \ m_map[algo]->data[AV_TRIPLE][Assembly::NONE] = cryptonight_triple_hash<algo, false>; \ m_map[algo]->data[AV_TRIPLE_SOFT][Assembly::NONE] = cryptonight_triple_hash<algo, true>; \ m_map[algo]->data[AV_QUAD][Assembly::NONE] = cryptonight_quad_hash<algo, false>; \ m_map[algo]->data[AV_QUAD_SOFT][Assembly::NONE] = cryptonight_quad_hash<algo, true>; \ m_map[algo]->data[AV_PENTA][Assembly::NONE] = cryptonight_penta_hash<algo, false>; \ m_map[algo]->data[AV_PENTA_SOFT][Assembly::NONE] = cryptonight_penta_hash<algo, true>; \ } while (0)

这个实现基于C++ template, 实现了处理单条消息,和2-5条消息并行计算的场景

我要处理的应该就是cryptonight_single_hash 这个函数

先编译下整个工程,编译成功后不知道怎么跑这个函数,感觉这个工程套的东西很多,工作量可能不是一天能处理的

再看看其他的还有https://github.com/xmrig/xmrig-cuda/blob/master/src/CryptonightR.cu 这个是gpu的实现,以后有空可以研究下

 

monero

https://github.com/monero-project/monero/tree/master/src/crypto 这个实现感觉简单的多,基本都是C的实现,感觉port起来应该容易的多