1

OMP を使用してBLAKEを並列化するには大きな問題があります。「コラムステップ」と「ダイアゴナルステップ」を並列化できることを仕様書で示唆した。これを実行しようとしましたが、結果は予想とは逆です (1 スレッドよりも 10 倍遅くなります)。このループを並列化する方法がわからないため、OMP の経験豊富なユーザーから少し助けが必要です :(

アップデート:

BLAKE の作者が BLAKE の改良 (高速) バージョンである BLAKE2 を公開したことは知っていますが、BLAKE とは実装 (ツリーハッシュ) が異なり、これを理解するのは非常に困難です。私の仕事は、OMP を使用して 1 スレッドとマルチスレッドの実装を比較することです。だから私は理解している実装でこれをやろうとします。私は OMP の専門家ではありません。可能な限り簡単な方法で BLAKE をマルチスレッド化したいと考えています。パフォーマンスが良くなくても、OMP で適切な実装を行う必要があります。(私の英語で申し訳ありませんが、あなたが私を理解してくれることを願っています)これは私のコードの一部です:

 #pragma omp parallel shared(n)
  {
 for(round=0; round<n; ++round) 
 {
/* column step, I want to run this 4 G32 functions in parallel, but don't know,
   that is proper approach to this problem */
        #pragma omp critical 
     G32( 0, 4, 8,12, 0);
        #pragma omp critical 
     G32( 1, 5, 9,13, 1);
        #pragma omp critical 
     G32( 2, 6,10,14, 2);
        #pragma omp critical 
     G32( 3, 7,11,15, 3);    

/* diagonal step, and same here */
        #pragma omp critical 
     G32( 0, 5,10,15, 4);
        #pragma omp critical 
     G32( 1, 6,11,12, 5);
        #pragma omp critical 
     G32( 2, 7, 8,13, 6);
        #pragma omp critical 
     G32( 3, 4, 9,14, 7);
}
}

そして、これは G32 関数です:

#define G32(a,b,c,d,i)\
 do { \
v[a] = ADD32(v[a],v[b])+XOR32(m[sigma[round][2*i]], c32[sigma[round][2*i+1]]);\
v[d] = ROT32(XOR32(v[d],v[a]),16);\
v[c] = ADD32(v[c],v[d]);\
v[b] = ROT32(XOR32(v[b],v[c]),12);\
v[a] = ADD32(v[a],v[b])+XOR32(m[sigma[round][2*i+1]], c32[sigma[round][2*i]]);\
v[d] = ROT32(XOR32(v[d],v[a]), 8);\
v[c] = ADD32(v[c],v[d]);\
v[b] = ROT32(XOR32(v[b],v[c]), 7);\
} while (0)
4

1 に答える 1

2

彼らが念頭に置いていた種類の並列化は、最新の CPU で SIMD 命令を利用することだったと思います。この場合の OMP スタイルの並列化には、次の 2 つの問題があります。

  • G32 タスクは「小さすぎる」または「短すぎる」ため、異なるスレッドでタスクを開始して結合することに関するオーバーヘッドが比較すると大きすぎます。
  • False Sharing: タスクで読み取られ、変更されるメモリの場所が近すぎます。それらはおそらくキャッシュラインを共有しています。これには特別な同期が必要であり、異なるスレッドからの読み取り/書き込みが非常に遅くなるため、これは悪いことです。
于 2013-01-10T15:53:41.777 に答える