非常基本的SSE

Really basic SSE

本文关键字:SSE 非常      更新时间:2023-10-16

我有一个非常简单的程序,我试图提高性能。我知道的一种方法是利用SSE3(因为我正在工作的机器支持这个),但我完全不知道如何做到这一点。下面是一个代码片段(c++):

int sum1, sum2, sum3, sum4;
for (int i=0; i<length; i+=4) {
  for (int j=0; j<length; j+=4) {
    sum1 = sum1 + input->value[i][j];
    sum2 = sum2 + input->value[i+1][j+1];
    sum3 = sum3 + input->value[i+2][j+3];
    sum4 = sum4 + input->value[i+3][j+4];    
  {
}

我读了一些关于这个的东西,并且理解了这个想法,但是我完全不知道如何实现它。有人能帮帮我吗?我认为这是相当简单的,特别是对于我的简单程序,但有时开始是最难的部分。

谢谢!

实际上,在您的情况下,事情并没有那么简单。现在,你的代码是NOT可矢量化的。(至少没有重要的循环转换)

这样做的原因是您在内部循环中也更改了索引i。由于内存位置不再相邻并且位于矩阵的不同行,因此中断了能够对j迭代进行矢量化的任何机会。(因为你似乎在对角线上运行矩阵)

然而,我得到的感觉是,你试图总结你的矩阵中的所有元素,你实际上打算你的循环是这样的(你也有一些错字):

int sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;
for (int i=0; i<length; i++) {
  for (int j=0; j<length; j+=4) {
    sum1 = sum1 + input->value[i][j];
    sum2 = sum2 + input->value[i][j+1];
    sum3 = sum3 + input->value[i][j+2];
    sum4 = sum4 + input->value[i][j+3];    
  }
}
int total = sum1 + sum2 + sum3 + sum4;

如果这是你想要的,那么它是非常可矢量化的。在使用内部函数的C/c++中,只需使用SSE2就可以这样做:

__m128i sum = _mm_setzero_si128();
for (int i=0; i<length; i++) {
  for (int j=0; j<length; j+=4) {
    __m128i val = _mm_load_si128(&input->value[i][j]);
    sum = _mm_add_epi32(sum,val);
  }
}

注意对齐限制将被应用。通过进一步展开循环,可以获得更多的加速。