0.3.6向けSSE2 CPUでの4ハッシュ並列処理
すごい…
つまり、128ビットレジスタを使って4つの32ビットデータを一度にSIMD処理しているということか? 長い間それを考えていたが、加算の桁上がりが隣の値に影響するため、不可能だと思っていた。
AMDでは2倍速で、Intelでは半分の速度ということか?
Quote from: tcatm on July 31, 2010, 10:12:38 AMちなみに、attribute ((aligned (16)))を使えばコンパイル時にコンパイラがアラインしてくれるのに、なぜalignup<16>関数を使っているのですか? 試したが、スタック上のものには機能しない。いくつかテストを行った。
エラーすら出ず、単にアラインされないだけだ。
Quote from: impossible7 on August 06, 2010, 11:37:20 AMCRITICAL_BLOCKはforループを含むマクロです。アサーション失敗はループ本体内でbreakが呼ばれたことを示しています。このブロック内の唯一のbreak文は2762行目にあります。元のソースファイルでは、このクリティカルブロック内にbreak文はありません。2759-2762行を削除すべきだと思います。元のmain.cppにはそのようなものはありません。 申し訳ない。CRITICAL_BLOCKは完璧ではない。その中からbreakやcontinueしないよう注意が必要だ。breakを検出して警告するassertがある。使用していることを批判されるかもしれないが、これなしでは構文がはるかに冗長でエラーが起きやすくなる。
SSE2コードがIntelで遅いのは、回避策がある何かの癖のせいだろうか? 例えば、アラインされていないと動作するが遅い、キャッシュスラッシングが起きている、または特定の種類の命令が本当に遅いなど。利用可能かどうかわからないが、Intelには命令単位でプロファイリングするプロファイラがあったと思う。tcatmが遅いプロセッサを搭載したテスト用システムを持っていなければ、あまり見込みはないだろう。でも、ほとんどのCPUで動作するようになると本当にいいのだが。
4倍や6倍のこれほど大きな速度差は、古いチップが苦手とする何か癖のある弱点や命令があるように感じる。SSE2を6倍速くしたというi5の売りの機能でない限りは。
要約:
Xeon Quad 41%低下
Core 2 Duo 55%低下
Core 2 Duo 変化なし(vess)
Core 2 Quad 50%低下
Core i5 200%向上(nelisky)
Core i5 100%向上(vess)
AMD Opteron 105%向上
aceat64: 私のシステムは約7100から約4200に低下しました。 このシステムはデュアルIntel Xeon Quad-Core CPU(E5335)@ 2.00GHzです。
impossible7: Intel Core 2 Duo T7300でx86_64 Linuxを実行したところ、ストック版(r121)と比べて55%低下しました
nelisky: 私のCore2Quad(Q6600)は50%低下しました、 i5は約200%向上しました、
impossible7: AMD Opteron 2374 HEでx86_64 Linuxを実行したところ、105%向上しました(!)
Windows上のMinGWでコンパイルに問題があります:
g++ -c -mthreads -O2 -w -Wno-invalid-offsetof -Wformat -g -D__WXDEBUG__ -DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH -I”/boost” -I”/db/build_unix” -I”/openssl/include” -I”/wxwidgets/lib/gcc_lib/mswud” -I”/wxwidgets/include” -msse2 -O3 -o obj/sha256.o sha256.cpp
sha256.cpp: In function `long long int vector Ch(long long int vector, long long int vector, long long int vector)’: sha256.cpp:31: internal compiler error: in perform_integral_promotions, at cp/typeck.c:1454 Please submit a full bug report, with preprocessed source if appropriate. See URL:http://www.mingw.org/bugs.shtml for instructions. make: *** [obj/sha256.o] Error 1
まだであれば、thashのアラインを試してみてほしい。効果があるかもしれない。損にはならない。
Quote from: tcatm on August 14, 2010, 12:53:07 AMツリーオプティマイザのコンパイラバグを引き起こしているようです。-O0でコンパイルしてみてもらえますか? -O0でも効果なし、同じエラーだ。
MinGWはGCC 3.4.5だ。おそらくそれが問題だ。
新しいバージョンのMinGWを入手できるか試してみる。
MinGW GCC 4.5.0: Crypto++が動作しない。X86_SHA256_HashBlocks()が返ってこない 4-wayはtest.cppでのみ動作するが、BitcoinMinerから呼び出された時は動作しない
MinGW GCC 4.4.1: Crypto++は動作する 4-wayはSIGSEGV
GCCは間違いなく__m128iをアラインしていない。
自分の__m128i変数をアラインしても、コンパイラが一時変数として裏で__m128iを使うことを決定する場合がある。
__m128i変数をアラインし、これらのインライン関数をdefineに変更することで、4.4.1の-O0のみで動作させることができた: #define Ch(b, c, d) ((b & c) ^ (~b & d)) #define Maj(b, c, d) ((b & c) ^ (b & d) ^ (c & d)) #define ROTR(x, n) (_mm_srli_epi32(x, n) | _mm_slli_epi32(x, 32 - n)) #define SHR(x, n) _mm_srli_epi32(x, n)
ただし、それは-O0での話だ。
MinGW GCC 4.4.1と4.5.0の両方で、test.cppでは動作するが、BitcoinMinerから呼び出されるとSIGSEGVになる。つまりGCCのバージョンの問題ではなく、別の何か、おそらくスタックのアラインメントの運によるものだろう。
Ubuntu 32ビットのGCC 4.3.3では問題なく動作している。
MinGW 4.5.0でのCrypto++の問題を見つけた。以下がそのパッチだ:
--- \old\sha.cpp Mon Jul 26 13:31:11 2010
+++ \new\sha.cpp Sat Aug 14 20:21:08 2010
@@ -336,7 +336,7 @@
ROUND(14, 0, eax, ecx, edi, edx)
ROUND(15, 0, ecx, eax, edx, edi)
- ASL(1)
+ ASL(label1) // Bitcoin: MinGW GCC 4.5用修正
AS2(add WORD_REG(si), 4*16)
ROUND(0, 1, eax, ecx, edi, edx)
ROUND(1, 1, ecx, eax, edx, edi)
@@ -355,7 +355,7 @@
ROUND(14, 1, eax, ecx, edi, edx)
ROUND(15, 1, ecx, eax, edx, edi)
AS2( cmp WORD_REG(si), K_END)
- ASJ( jne, 1, b)
+ ASJ( jne, label1, ) // Bitcoin: MinGW GCC 4.5用修正
AS2( mov WORD_REG(dx), DATA_SAVE)
AS2( add WORD_REG(dx), 64)