15

どのように使用します__m256dか?

3〜64ビット精度のコンポーネント(、、、および)を_mm256_add_pd持つ単純なクラスでIntelAVX命令を使用したいとします。これを使用する正しい方法は何ですか?Vector3doublexyz

x、はクラスのメンバーなのでy、 _変数を使用して宣言できますか?zVector3union__m256d

union Vector3
{
  struct { double x,y,z ; } ;
  __m256d _register ;  // the Intel register?
} ;

それなら私は行くことができます:

Vector3 add( const Vector3& o )
{
  Vector3 result;
  result._register = _mm256_add_pd( _register, o._register ) ; // add 'em
  return result; 
}

それはうまくいくでしょうか?または、一時的なものを宣言する必要がありますか?

Vector3 add( const Vector3& o )
{
  __m256d d1 = *(__m256d*)(&x) ; // ? Cast to __m256d?
  __m256d d2 = *(__m256d*)(&o.x) ; // ? Cast to __m256d?
  __m256d result = _mm256_add_pd( d1, d2 ) ; // add 'em
  return Vector3( result ) ; // make a ctor that accepts __m256d?
}

編集

私はこの例を思いついた、

#include <stdio.h>
#include <intrin.h>

int main()
{
  __m256d a, b, res;

  for( int i = 0; i < sizeof(__m256d)/sizeof(double); i++ )
  {
    a.m256d_f64[i] = i ;
    b.m256d_f64[i] = 2*i ;
  }

  // Perform __4__ adds.
  res = _mm256_add_pd(a, b);

  for( int i = 0; i < sizeof(__m256d)/sizeof(double); i++ )
  {
    printf("%f + %f = %f\n", a.m256d_f64[i], b.m256d_f64[i], res.m256d_f64[i]);
  }
  puts("");
}

問題は、ロード操作を自動的に実行するのか、それとも、レジスターを使用場所に近いローカルとして宣言しない と、何かが混乱するのかということだと思います。(ホテルの部屋/机の引き出しタイプの問題が怖いです)_mm256_add_pd__m256d

編集2:

かなり大きなプロジェクトにレジスターを追加してみた__m256ところ、たくさんの

エラーC2719:'value':__declspec(align( '32'))を含む正式なパラメーターは整列されません

エラー、それはあなたがクラス内にレジスタを保持することはできないと私に信じさせます__m256、代わりにそれらはローカルとして宣言されるべきですか?

4

1 に答える 1

16

まず、少し混乱を解消したいと思います。 レジスタのタイプではなく、AVX レジスタにロードできる__m256dデータ タイプです。がレジスタである以上、Aはレジスタではありません。(またはその他のベクター型)にデータを出し入れするには、いくつかの方法があります。__m256dint__m256d

a の使用union:はい、このunionトリックは機能します。共用体は一般に正しいアライメントを持つため、非常にうまく機能します (そうでない場合もありますが、 ormallocを使用します)。posix_memalign_aligned_malloc

class Vector3 {
public:
    Vector3(double xx, double yy, double zz);
    Vector3(__m256d vvec);


    Vector3 operator+(const Vector3 &other) const
    {
        return Vector3(_mm256_add_pd(vec, other.vec));
    }

    union {
        struct {
            double x, y, z;
        };
        __m256d vec; // a data field, maybe a register, maybe not
    };
};

組み込み関数の使用:通常、関数内では、組み込み関数を使用してベクター型のデータを入出力する方が簡単です。

__m256d vec = ...;
double x, y, z;
vec = _mm256_add_pd(vec, _mm256_set_pd(x, y, z, 0.0));

ポインター キャストの使用:いくつかの理由から、ポインターのキャストは最後の手段です。

  1. ポインターが正しく配置されていない可能性があります。

  2. ポインタをキャストすると、コンパイラのエイリアシング分析が混乱することがあります。

  3. ポインターのキャストは、多くの安全保証をバイパスします。

したがって、ポインターのキャストは、大量のデータ配列を処理するためにのみ使用します。

于 2012-10-14T01:11:58.627 に答える