gcc内存对齐pragma

时间:2010-04-21 23:20:29

标签: optimization memory gcc alignment pragma

gcc在英特尔编译器中是否有内存对齐编译指示,类似#pragma vector aligned? 我想告诉编译器使用对齐的加载/存储指令优化特定的循环。为了避免可能的混淆,这不是关于结构包装。

e.g:

#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);
        }

由于

3 个答案:

答案 0 :(得分:10)

你可以告诉GCC指针指向对齐的内存,方法是使用typedef来创建一个可以声明指针的过度对齐类型。

这有助于gcc而不是clang7.0或ICC19,请参阅x86-64非AVX asm,它们会发出on Godbolt 。 (只有GCC会将负载折叠到mulps的内存操作数中,而不是使用单独的movups)。如果你想向GCC本身以外的GNU C编译器移植一个对齐承诺,你必须使用__builtin_assume_aligned


来自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代码,但我认为这可以满足您的需求。

(注意:我测试时没有使用double,因为altivec不支持双浮点数。)

您可以在此处使用类型属性查看自动向量化的其他一些示例:http://gcc.gnu.org/projects/tree-ssa/vectorization.html

答案 1 :(得分:5)

我尝试使用g ++版本4.5.2(Ubuntu和Windows)的解决方案,并且对循环进行矢量化。

如果删除了alignment属性,则使用未对齐的加载来对循环进行矢量化。

如果函数是内联的,那么可以在删除指针的情况下直接访问数组,然后使用对齐的加载进行矢量化。

在这两种情况下,alignment属性都会阻止矢量化。具有讽刺意味的是:“aligned_double * x”应该能够实现矢量化,但却恰恰相反。

为您报告矢量化循环的是哪个编译器?我怀疑它不是gcc编译器?

答案 2 :(得分:3)

  

gcc是否具有内存对齐编译指示,类似于#pragma vector aligned

看起来新版本的GCC有__builtin_assume_aligned

  

内置函数:void * __builtin_assume_aligned (const void *exp, size_t align, ...)

     

此函数返回其第一个参数,并允许编译器假定返回的指针至少对齐字节对齐。   这个内置可以有两个或三个参数,如果它有三个,   第三个参数应该是整数类型,如果它是非零的   意味着错位偏移。例如:

void *x = __builtin_assume_aligned (arg, 16);
     

表示编译器可以假设x(设置为arg)至少为16字节对齐,而:

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

表示编译器可以假设为x,设置为arg,(char *)x - 8是32字节对齐的。

基于Stack Overflow大约2010年的一些其他问题和答案,看起来内置在GCC 3和早期GCC 4中不可用。但我不知道截止点在哪里。