7

私はいくつかの高速数学計算を行う必要があるCでプログラムを書いています。インラインSSEアセンブリ命令を使用して、SIMDアクションを取得しています(パックされた倍精度浮動小数点数を使用)。LinuxでGCCを使用してコンパイルしています。

一部のデータをループする必要がある状況にあり、計算に定数係数を使用しています。ループ中はその要素を安全なレジスタに隠しておきたいので、毎回再ロードする必要はありません。

いくつかのコードで明確にするには:

struct vect2 {
    fltpt x;
    fltpt y;
}__attribute__((aligned(16))); /* Align on 16B boundary for SSE2 instructions */
typedef struct vect2 vect2_t;


void function()
{
    /* get a specific value set up in xmm1, and keep it there for the 
     * rest of the loop. */
    for( int i = 0, i<N; i++ ){
        asm(
            "Some calculations;"
            "on an element of;"
            "a data set.;"
            "The value in xmm1;"
            "is needed;"
        );
    }
}

「register」キーワードで何かしてみました。しかし、私が間違っていなければ、その構造体へのポインターしか(一般的なレジスターに)保持できないように見えます。これは、反復ごとに延期する必要があり、貴重な時間を無駄にします。

register vect2_t hVect asm("xmm1") = {h, h};
/* Gives error: data type of 'hVect' isn't suitable for a register */

register vect2_t *hVect2 asm("rax");
*hVect2 = (vect2_t){h,h};
/* Seems to work, but not what I'm looking for */

GCCがxmm1レジスタを変更しないと仮定するのは好きではありません。それは、「鼻から飛び出す悪魔」のようなものではありません:-)。だから私はこれを行うための適切な方法があることを望んでいます。

4

3 に答える 3

8

ここでの解決策は、gccにあなたのvec2_t型が実際にはベクトルであることを認識させることだと思います。次に、ループ不変値を計算して、それを正規変数として扱うことができます(コンパイラがそれがベクトル型であることを認識している場合を除く)。

typedef double vec2_t __attribute__ ((vector_size (16)));

void function()
{
  /* get a specific value set up, e.g. */
  vec2_t invariant;
  asm( "some calculations, soring result in invariant."
       : "=x" (invariant) );

  for( int i = 0; i<N; i++ ){
    asm(
            "Some calculations;"
            "on an element of;"
            "a data set.;"
            "The value in xmm1;"
            "is needed;"
            : "x" (invariant) // and other SSE arguments
       );
   }
}

ループ内の簡単な計算でこれをまとめました。少なくとも最適化レベル1では、の値はinvariantループ中にXMMレジスタに保持されます。

(これはすべて、明示的なXMMレジスタでループ不変条件を必要としないこと、およびGCCの通常のレジスタ割り当てを使用できることを前提としています)。

于 2009-08-08T23:59:28.270 に答える
3

レジスタの割り当てはコンパイラに任せるのが最善だと思います。それはおそらくあなたよりもそれをよりよく追跡することができます。GCCはすでにSSE拡張命令を使用しますが、よく知っている場合は、GCC__builtin関数を使用してください。正直なところ、そうすればもっと速くなるのではないかと少し疑っています。

頑張ってください!

これらのサイトはおそらく見るのが面白いでしょう。

GCCX86組み込み関数

GCCでのSIMDの操作

于 2009-08-09T00:07:12.653 に答える
3

私はアセンブリとCでの作業に慣れており、ここで行うことは、関数全体をアセンブリで記述することです。柔軟なmakeシステムを使用している場合は、ASM関数を個別にアセンブルし、アプリケーションにリンクすることをお勧めします。これに関する唯一の問題は、関数をコンパイラーがインライン化できないことです。

void function(void); // C

extern "C"関数(void); // C ++

于 2009-08-09T01:10:29.793 に答える