2016-07-19 6 views
2

4つの倍精度値を持つAVXレジスタがあります。今は、各要素ごとに個別に算術演算を行う必要があります。私がしなければならないことの半分化は以下の通りです。AVXレジスタの内容を無効にする

Situation: 
    a = [a4 a3 a2 a1] 
    w = [ 0 0 0 w1] 
    x = [ 0 0 0 x1] 
    y = [ 0 0 0 y1] 
    z = [ 0 0 0 z1] 

Desired result: 
    w = [-- -- -- w1+a1] 
    x = [-- -- -- x1+a2] 
    y = [-- -- -- y1+a3] 
    z = [-- -- -- z1+a4] 

目的の結果は、2つの値の合計だけではなく、それらのより複雑な算術式を除いています。私が--と書いたところでは、私はそれらの値を気にしないで捨てるという意味です。

私は、置換演算を使用してレジスタaを並べ替えることができました(例:Reverse a AVX register containing doubles using a single AVX intrinsicを参照)。私の唯一の問題は、これらのコンパイラ組み込み関数がこの操作を動的に実行する必要がある間に、コンパイル時の値を即座に必要とすることです。

私は_mm256_permutevar_pdのように、他のレジスタに含まれる整数で動作する順列組み込み関数を発見したが、並び替えるレーン間でそれらのどれも(例えば、それは最初の場所でa3を持つように、これらの命令を使用しては不可能であろう。何を行うための唯一の方法

ifの条件に従う128ビットのレーンで並べ替えを行い、その後にレーン内の動的並べ替えを行う必要がありますか、それとも良い解決策がありますか?私はパフォーマンスと保守性の両方に興味があります。私はAVX2命令まで使うことができます。組み立てはオプションですが、私は組み込み関数が好きです。

+1

メモリにベクトルとして格納し、スカラーとして読み込みますか? –

+0

私はそのような解決策から離れたときに、私のアプリケーションに大きなスピードアップがありました。私はすでに「メモリ内のストア」​​ソリューションを実装しました。今度は、全体の操作がレジスタで行われるときの違いを見たいと思います。 – Spiros

+0

結果は4つの独立したスカラー倍として結果が必要ですか? (これは、他の要素が関与していないベクトルの低い要素にあるのと同じことです)。非コンパイル時定数シャッフルはどこに入っていますか?なぜあなたは 'vextractf128'を使って解凍し、' __m128d'の上位半分を 'vmovhlps'などでスカラー' double'にすることができないのか分かりません。あなたはどのベクトル要素がどの変数名になるか知っています... –

答えて

1

[ z y x w ]をベクターにパックした後、+が表すものは何でも構いません。しかし、そうでない場合:

エキス、すべての4つの要素doubleの通常の方法をスカラー、その後、あなたがやりたいために:

void unpack_256_to_scalar(__m256d a) { 
    // unpack to two 128b halves 
    __m128d a01 = _mm256_castpd256_pd128(a); // extractf128_pd(a, 0) should also compile the same way, if you like more-consistent C instead of code that matches the asm you expect 
    __m128d a23 = _mm256_extractf128_pd(a, 1); 

    // and then halves of each 128b vector 
    double a0 = _mm_cvtsd_f64(a01); 
    double a1 = _mm_cvtsd_f64(_mm_unpackhi_pd(a01,a01)); 
    double a2 = _mm_cvtsd_f64(a23); 
    double a3 = _mm_cvtsd_f64(_mm_unpackhi_pd(a23,a23)); 
    ... 
    // use the results 
} 

このcompiles (on the Godbolt compiler explorer) 3つしか打ち鳴らすとの指示、またはGCCと4にそれがされていますので、レジスタ割り当てとダム:

unpack_256_to_scalar(double __vector(4)): 
    vextractf128 xmm1, ymm0, 0x1 
    vunpckhpd  xmm2, xmm0, xmm0 
    vmovapd xmm3, xmm1     # gcc should have use vunpckhpd xmm3, xmm1,xmm1. This wasted mov is a missed-optimization bug. 
    vunpckhpd  xmm1, xmm1, xmm1 
    # the empty asm statement emitted the empty string here. 
    vzeroupper 
    ret 

3つの命令の各々は、そのベクトルの結果の低い要素として異なるエレメントを生成します。いいえ定数は(私がunpackhi_pd代わりshufpdか、データ移動の内部表現からシャッフルを生成だ時に打ち鳴らすが使用するvpermilpdの選んだ理由である。)、いなくてもすぐに定数を必要ありません

が必要と可変シャッフルを使用して制御マスクとしてのベクトルはここでは狂っているでしょう。これについては、動的/可変シャッフルまたは抽出を必要とするものはありません。

ところで、高性能コードの作成に関するいくつかのリンクについては、タグwikiを参照してください。

関連する問題