3
int u1, u2;  
unsigned long elm1[20], _mulpre[16][20], res1[40], res2[40]; 64 bits long     
res1, res2 initialized to zero.  

l = 60;  
while (l)  
{  
    for (i = 0; i < 20; i += 2)  
    {  
        u1 = (elm1[i] >> l) & 15;  
        u2 = (elm1[i + 1] >> l) & 15;

        for (k = 0; k < 20; k += 2)  
        {  
            simda = _mm_load_si128 ((__m128i *) &_mulpre[u1][k]);  
            simdb = _mm_load_si128 ((__m128i *) &res1[i + k]);  
            simdb = _mm_xor_si128  (simda, simdb);  
            _mm_store_si128 ((__m128i *)&res1[i + k], simdb);  

            simda = _mm_load_si128 ((__m128i *)&_mulpre[u2][k]);  
            simdb = _mm_load_si128 ((__m128i *)&res2[i + k]);  
            simdb = _mm_xor_si128  (simda, simdb);  
            _mm_store_si128 ((__m128i *)&res2[i + k], simdb);  
        } 
    }
    l -= 4;
    All res1, res2 values are left shifted by 4 bits.  
}

上記のコードは私のプログラムで何度も呼び出されます (プロファイラーは 98% を示します)。

編集: 内側のループでは、同じ (i + k) 値に対して res1[i + k] 値が何度も読み込まれます。while ループ内でこれを試してみました。すべての res1 値を simd レジスタ (配列) にロードし、最も内側の for ループ内で配列要素を使用して配列要素を更新しました。両方の for ループが完了したら、配列の値を res1、re2 に保存しました。しかし、これにより計算時間が増加します。私がどこで間違ったのか分かりますか?その考えは正しかったようです

より速くするための提案は大歓迎です。

4

4 に答える 4

2

残念ながら、最も明白な最適化はおそらくコンパイラーによって既に行われています。

  • 内側のループの部分を引っ張っ&_mulpre[u1]ていただくことができます。&mulpre[u2]
  • &res1[i]内側のループを引っ張ることができます。
  • 2 つの内部操作に異なる変数を使用し、それらを並べ替えると、パイプライン処理が改善される可能性があります。

外側のループを交換すると、上のキャッシュの局所性が向上する可能性がありelm1ます。

于 2010-12-15T14:15:23.060 に答える
0

まあ、あなたはいつもそれをより少ない回数と呼ぶことができます:-)

設計と予想される入力によっては、入力と出力の合計データが比較的小さく見える場合があります。事前に計算するのではなく、計算をキャッシュするか、遅延評価を行うことが可能な場合があります。

于 2010-12-15T14:31:08.230 に答える
0

ロードとストアが支配的な要因になるため、このようなルーチンでできることはほとんどありません(1つの計算命令に対して2つのロード+1ストア=4バスサイクルを実行します)。

于 2010-12-15T14:33:08.963 に答える
0
l = 60;  
while (l)  
{  
    for (i = 0; i < 20; i += 2)  
    {  
        u1 = (elm1[i] >> l) & 15;  
        u2 = (elm1[i + 1] >> l) & 15;

        for (k = 0; k < 20; k += 2)  
        {  
            _mm_stream_si128 ((__m128i *)&res1[i + k],
                    _mm_xor_si128  (
                                    _mm_load_si128 ((__m128i *) &_mulpre[u1][k]),
                                    _mm_load_si128 ((__m128i *) &res1[i + k]
                                   ));  

            mm_stream_si128 ((__m128i *)&res2[i + k],    
                    _mm_xor_si128  (
                                    _mm_load_si128 ((__m128i *)&_mulpre[u2][k]), 
                                    _mm_load_si128 ((__m128i *)&res2[i + k])
                                   ));  
        } 
    }
    l -= 4;
    All res1, res2 values are left shifted by 4 bits.  
}
  1. _ 128mi/ _mm128 の値を少なくすると、プログラムが高速化されます。
  2. _mm_stream_si128() を試すと、保存プロセスが高速化される場合があります。
  3. プリフェッチを試す
于 2010-12-23T14:19:53.040 に答える