8

gccには#pragma vector aligned、Intelコンパイラと同様のメモリアライメントプラグマがありますか?整列されたロード/ストア命令を使用して特定のループを最適化するようにコンパイラーに指示したいと思います。混乱を避けるために、これは構造体のパッキングに関するものではありません。

例えば:

#if defined (__INTEL_COMPILER)
#pragma vector aligned
#endif
        for (int a = 0; a < int(N); ++a) {
            q10 += Ix(a,0,0)*Iy(a,1,1)*Iz(a,0,0);
            q11 += Ix(a,0,0)*Iy(a,0,1)*Iz(a,1,0);
            q12 += Ix(a,0,0)*Iy(a,0,0)*Iz(a,0,1);
            q13 += Ix(a,1,0)*Iy(a,0,0)*Iz(a,0,1);
            q14 += Ix(a,0,0)*Iy(a,1,0)*Iz(a,0,1);
            q15 += Ix(a,0,0)*Iy(a,0,0)*Iz(a,1,1);
        }

ありがとう

4

3 に答える 3

10

typedefを使用して、ポインターを宣言できるオーバーアラインされた型を作成することにより、ポインターがアラインされたメモリーを指していることをGCCに伝えることができます。

これはgccには役立ちますが、clang7.0やICC19には役立ちません。Godboltで出力されるx86-64非AVXasmを参照してくださいmulps(GCCのみが、個別のを使用する代わりに、のメモリオペランドに負荷をフォールドしますmovups)。__builtin_assume_alignedGCC自体以外のGNUCコンパイラにアライメントの約束を移植可能に伝えたい場合は、を使用する必要があります。


http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.htmlから

typedef double aligned_double __attribute__((aligned (16)));
// Note: sizeof(aligned_double) is 8, not 16
void some_function(aligned_double *x, aligned_double *y, int n)
{
    for (int i = 0; i < n; ++i) {
        // math!
    }
}

aligned_doubleこれにより、 16バイト幅にはなりません。これにより、16バイトの境界に揃えられるか、配列の最初の境界に揃えられます。コンピューターで逆アセンブルを見ると、アライメントディレクティブを使用するとすぐに、多くのベクトル演算が表示され始めます。私は現在Powerアーキテクチャコンピュータを使用しているので、それはAltivecコードですが、これはあなたが望むことをしていると思います。

(注:doublealtivecはダブルフロートをサポートしていないため、これをテストしたときは使用していませんでした。)

ここでtype属性を使用した自動ベクトル化の他の例を見ることができます:http://gcc.gnu.org/projects/tree-ssa/vectorization.html

于 2010-04-21T23:40:19.413 に答える
5

g ++バージョン4.5.2(UbuntuとWindowsの両方)でソリューションを試しましたが、ループがベクトル化されませんでした。

アラインメント属性が削除されると、アラインされていないロードを使用してループがベクトル化されます。

関数がインライン化されているため、ポインターを削除して配列に直接アクセスできる場合は、整列された負荷でベクトル化されます。

どちらの場合も、アライメント属性はベクトル化を防ぎます。これは皮肉なことです。「aligned_double*x」はベクトル化を有効にするはずでしたが、その逆です。

ベクトル化されたループを報告したのはどのコンパイラでしたか?gccコンパイラではなかったと思いますか?

于 2011-08-09T14:21:17.763 に答える
3

gccにはメモリアライメントプラグマがありますか?#pragmavectoralignedに似ています

GCCの新しいバージョンには次のものがあるようです__builtin_assume_aligned

組み込み関数:void * __builtin_assume_aligned (const void *exp, size_t align, ...)

この関数は最初の引数を返し、コンパイラーは、返されたポインターが少なくともバイト整列されていると想定できるようにします。このビルトインは2つまたは3つの引数を持つことができ、3つある場合は、3番目の引数は整数型である必要があります。ゼロ以外の場合は、ミスアラインメントオフセットを意味します。例えば:

void *x = __builtin_assume_aligned (arg, 16);

これは、コンパイラがargに設定されたxが少なくとも16バイト整列されていると想定できることを意味します。

void *x = __builtin_assume_aligned (arg, 32, 8);

これは、コンパイラがargに設定されたxについて、(char *)x-8が32バイトに整列されていると想定できることを意味します。

2010年頃のStackOverflowに関する他のいくつかの質問と回答に基づくと、組み込みはGCC3と初期のGCC4では利用できなかったようです。しかし、カットオフポイントがどこにあるかはわかりません。

于 2017-03-27T06:24:42.247 に答える