18

4 つの 64 ビット浮動小数点値でパックされた __m256d ベクトルがあります。
ベクトルの要素の水平方向の最大値を見つけて、結果を倍精度スカラー値に格納する必要があります。

私の試みはすべて、ベクトル要素のシャッフルを大量に使用することになり、コードはあまりエレガントでも効率的でもありませんでした。また、AVX ドメインだけにとどまることは不可能であることがわかりました。ある時点で、SSE 128 ビット命令を使用して最終的な 64 ビット値を抽出する必要がありました。ただし、この最後のステートメントで私が間違っていることを証明したいと思います。

したがって、理想的なソリューションは次のとおりです
。1) AVX 命令のみを使用します。
2) 命令の数を最小限に抑えます。(私は 3-4 以上の命令を望んでいません)

そうは言っても、上記のガイドラインに準拠していなくても、エレガントで効率的なソリューションは受け入れられます。

助けてくれてありがとう。

-ルイージ

4

3 に答える 3

22

4 つの命令 (2 つのシャッフルと 2 つの比較) よりもはるかに優れているとは思いません。

__m256d x = ...; // input

__m128d y = _mm256_extractf128_pd(x, 1); // extract x[2], and x[3]
__m128d m1 = _mm_max_pd(x, y); // m1[0] = max(x[0], x[2]), m1[1] = max(x[1], x[3])
__m128d m2 = _mm_permute_pd(m1, 1); // set m2[0] = m1[1], m2[1] = m1[0]
__m128d m = _mm_max_pd(m1, m2); // both m[0] and m[1] contain the horizontal max(x[0], x[1], x[2], x[3])

256 ビットのベクトルでのみ機能するように簡単に変更します。

__m256d x = ...; // input

__m256d y = _mm256_permute2f128_pd(x, x, 1); // permute 128-bit values
__m256d m1 = _mm256_max_pd(x, y); // m1[0] = max(x[0], x[2]), m1[1] = max(x[1], x[3]), etc.
__m256d m2 = _mm256_permute_pd(m1, 5); // set m2[0] = m1[1], m2[1] = m1[0], etc.
__m256d m = _mm256_max_pd(m1, m2); // all m[0] ... m[3] contain the horizontal max(x[0], x[1], x[2], x[3])

(未テスト)

于 2012-03-21T07:43:54.790 に答える
12

ベクトルに対してこれを行う一般的な方法は次のとおりv1 = [A, B, C, D]です。

  1. 順列(0番目と2番目の要素、および1番目と3番目の要素を入れ替えるv1v2 = [C, D, A, B]
  2. 最大を取る; すなわちv3 = max(v1,v2)。あなたは今持っています[max(A,C), max(B,D), max(A,C), max(B,D)]
  3. 0番目と1番目の要素、および2番目と3番目の要素を入れ替えて置換v3します。v4
  4. もう一度最大値を取りv5 = max(v3,v4)ます。v5これで、すべてのコンポーネントに水平方向の最大値が含まれます。

特にAVXの場合、順列はで実行でき_mm256_permute_pd、最大値はで実行できます_mm256_max_pd。私は正確な順列マスクを手元に持っていませんが、それらを理解するのはかなり簡単なはずです。

お役に立てば幸いです。

于 2012-03-21T03:51:17.757 に答える
3
//Use the code to find the horizontal maximum
__m256 v1 = initial_vector;//example v1=[1 2 3 4 5 6 7 8]
__m256 v2 = _mm256_permute_ps(v1,(int)147);//147 is control code for rotate left by upper 4 elements and lower 4 elements separately v2=[2 3 4 1 6 7 8 5]
__m256 v3 = _mm256_max_ps(v1,v2);//v3=[2 3 4 4 6 7 8 8]
__m256 v4 = _mm256_permute_ps(v3,(int)147);//v4=[3 4 4 2 7 8 8 6]
__m256 v5 = _mm256_max_ps(v3,v4);//v5=[3 4 4 4 7 8 8 8]
__m256 v6 = _mm256_permute_ps(v5,(int)147);//v6=[4 4 4 3 8 8 8 7]
__m256 v7 = _mm256_max_ps(v5,v6);//contains max of upper four elements and lower 4 elements. v7=[4 4 4 4 8 8 8 8]

//to get max of this horizontal array. Note that the highest end of either upper or lower can contain the maximum
float ALIGN max_array[8];
float horizontal_max;
_mm256_store_ps(max_array, v7);
if(max_array[3] > max_array[7])
{
    horizontal_max = max_array[3];
}
else
{
    horizontal_max = max_array[7];
}
于 2015-10-30T06:49:28.230 に答える