#mining thread
実際のハッシュ計算処理のAVX2化とかは別の人がやっているので、処理の流れを見ながら気づいた点とかのメモ
1.while(1)ループ内にif文が多い。それも起動時にフラグが確定するようなので
最近のCPUの分岐予測は賢くなっているし、コンパイラも賢くなっているので、どれだけ効果があるか分からないが、
ループ中の条件分岐は少なければ少ない方が条件分岐予測を間違って投機実行している分が無駄になるということが減る。
条件分岐ではなく、数値演算で同じ値を導くようにする。
2.内部で変わらない数値計算はループの外に出す。
ループの外で計算して変数に入れておく。
3.time(NULL)とか時間取得関数とか
システムコールなので遅い。使う頻度を減らすとか。
全体的な感想としては、とても素直にロジックを組んであって読みやすい。
一方で高速化という点は考慮されていないように見える。
実行ログを見ていると、while(1)ループは1秒に1回くらいしかループしていないようなので、やらなくていいんじゃないかな感ある。
#yescrypt_bitzeny()
スレッドごとに初期化する処理がここに入っているが、無駄なのでループの外に出すべき。
あと、エラーがあったときも戻り値使用してないけど再初期化とかいらないのかしら?
#pretest()
宣言にinline追加
#yescrypt_hash()
宣言にinline追加
#yescrypt_kdf()
乗算・除算をシフト演算に置き換える(コンパイラーがやる気がする)
同じ演算内容を変数に格納して使う。
#smix(),smix1(),smix2()
yescriptに限定すれば処理の簡略化ができる。
それにしても条件分岐が多い。確かにGPU向きじゃない。Radeon(OpenCL)なら対応できるかもしれないけどGeForce(CUDA)では無理か向かない。
→乗算除算をシフト演算に、剰余算をビット演算に、乗算を加算に置き換えることで0.1kh/s(0.7%)改善
#work.data
data[0]:job.version
data[1-8]:job.prevhash
data[9-16]:merkle_root
data[17]:job.ntime
data[18]:job.nbits
data[19]:現在計算した最大Nonce
https://bitflyer.jp/ja/glossary/Nonce
ハッシュレートの計算に使われる。
data[20]:0x80000000
data[31]:0x00000280
#miner_thread()のバグ?
uint32_t end_nonce = 0xffffffffU / opt_n_threads * (thr_id + 1) - 0x20;
スレッド毎に使用するNonceの範囲を均等に割り当てているようだが、0x20の意味は?
開始Nonceは下記の式で決まっているので、
work.data[19] = 0xffffffffU / opt_n_threads * thr_id;
計算されないNonceが約0x20 * スレッド数になるのでバグ(本来見つかるべきBlockを見落とす可能性がある)なのでは?
例えば16スレッドの場合に16番目(thr_id=15)のend_nonceは
0xffffffff:0xffffffffU
0x0fffffff:0xffffffffU / opt_n_threads
0xfffffff0:0xffffffffU / opt_n_threads * (thr_id + 1)
0xffffffd0:0xffffffffU / opt_n_threads * (thr_id + 1) - 0x20
となる。
「- 0x20」を削る必要と、
if(opt_n_threads == (thr_id + 1)){
end_nonce = 0xffffffffU;
}
が必要だろう。
ハッシュの計算を0x20Nonce単位で行っている可能性もあるが、その場合スレッド間で計算領域が重複している。
*Nonceの進捗が++nでループしていたからそれも無いと思う。
フォーラムで報告中
Nonceの割当をスレッドに対して均等に行っているとすると、計算スレッド数はコア数か論理CPU数(-通信とかOS用)がボトルネックが無くなって良いことになる。
下手にスレッド数を増やすと、遅いスレッドの計算完了待ち時間が発生していて表示上現れないハッシュレートの低下が起きている?