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 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 函数。老实说,我有点怀疑你会不会让它变得更快。

祝你好运!

这些网站可能很有趣。

GCC X86 内置函数

与 GCC 一起使用 SIMD

于 2009-08-09T00:07:12.653 回答
3

我习惯于使用汇编和 C 语言,我在这里要做的就是用汇编语言编写整个函数。如果您有一个灵活的 make 系统,我建议单独组装 ASM 功能并将其链接到您的应用程序中。唯一的问题是编译器不能内联函数。

无效函数(无效);//C

外部“C”函数(无效);//C++

于 2009-08-09T01:10:29.793 回答