1

我有一个非常简单的程序,我正在尝试提高性能。我知道会有所帮助的一种方法是利用 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];    
  {
}

我已经阅读了一些关于这个的内容,并且理解了这个想法,但我完全不知道如何实现这个。有人可以帮我吗?我认为这相当简单,尤其是对于我的简单程序,但有时入门是最难的部分。

谢谢!

4

1 回答 1

5

实际上,就您而言,这并不是那么简单。就目前而言,您的代码不可矢量化。(至少不是没有显着的循环转换)

这样做的原因是您正在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);
  }
}

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

于 2011-11-02T05:43:05.563 回答