3

SSE3 コマンドを使用するために、いくつかの既存のベクトルおよび行列クラスを再実装しようとしましたが、ベクトルの配列に対して一連の操作を実行するたびに、これらの「メモリ アクセス違反」エラーが発生しているようです。私は SSE に比較的慣れていないので、単純なものから始めています。これが私のベクトルクラスの全体です:

class SSEVector3D
{
public:

   SSEVector3D();
   SSEVector3D(float x, float y, float z);

   SSEVector3D& operator+=(const SSEVector3D& rhs); //< Elementwise Addition

   float x() const;
   float y() const;
   float z() const;

private:

   float m_coords[3] __attribute__ ((aligned (16))); //< The x, y and z coordinates

};

したがって、まだ多くは行われておらず、いくつかのコンストラクター、アクセサー、および 1 つの操作のみです。私の (確かに限られた) SSE の知識を使用して、次のように追加操作を実装しました。

SSEVector3D& SSEVector3D::operator+=(const SSEVector3D& rhs) 
{
   __m128 * pLhs = (__m128 *) m_coords;
   __m128 * pRhs = (__m128 *) rhs.m_coords;

   *pLhs = _mm_add_ps(*pLhs, *pRhs);

   return (*this);
}

古いベクトル クラスに対して新しいベクトル クラスの速度をテストする (全体を再実装する価値があるかどうかを確認する) ために、SSEVector3D オブジェクトのランダムな配列を生成してそれらを追加する簡単なプログラムを作成しました。複雑すぎません:

SSEVector3D sseSum(0, 0, 0);

for(i=0; i<sseVectors.size(); i++)
{
   sseSum += sseVectors[i];
}

printf("Total: %f %f %f\n", sseSum.x(), sseSum.y(), sseSum.z());

変数は、タイプのsseVectors要素を含む std::vectorであり、そのコンポーネントはすべてとSSEVector3Dの間の乱数に初期化されます。-11

これが私が抱えている問題です。のサイズが (試行錯誤を重ねてたどり着いた数値) 以下であればsseVectors問題8,191なく動作します。サイズが8,192以上の場合、実行しようとすると次のエラーが発生します。

signal: SIGSEGV, si_code: 0 (アドレス: 0x00000080 でメモリアクセス違反)

しかし、その print 文を最後にコメントアウトするとsseVectors、サイズが 8,192 以上であってもエラーになりません。

このベクトル クラスの書き方に何か問題がありますか? GCC バージョン 4.6 で Ubuntu 12.04.1 を実行しています

4

2 に答える 2

1

何よりもまず、これをしないでください

__m128 * pLhs = (__m128 *) m_coords;
__m128 * pRhs = (__m128 *) rhs.m_coords;
*pLhs = _mm_add_ps(*pLhs, *pRhs);

SSE では、単に逆参照するだけではなく、常に適切な組み込み関数を介して明示的にロードとストアを実行してください。クラスに 3 つの float の配列を格納する代わりに、 type の値を格納します。これにより、属性を必要とせずに、コンパイラがクラスのインスタンスを正しく整列させるはずです。_m128align

ただし、これは MSVC ではうまく機能しないことに注意してください。MSVC は一般に、値による引数に対して 8 バイト アラインメントよりも強いアラインメント要件に対処できないようです :-(. 前回、SSE コードを Windows に移植する必要があったとき、私の解決策は、SSE 部分に Intel の C++ コンパイラを使用することでした。 MSVCの代わりに...

于 2012-10-01T11:45:44.717 に答える
0

__m128トリックは、それが 16 バイトでアラインされていることに注意することです。を使用_malloc_aligned()して、float 配列が正しく配置されていることを確認してから、float を の配列にキャストできます__m128。割り当てるフロートの数が 4 で割り切れることも確認してください。

于 2014-01-16T03:25:52.133 に答える