SSE3内置函数:如何找到大型浮点数组的最大值

7
我有以下代码来查找最大值。
int length = 2000;
float *data;
// data is allocated and initialized

float max = 0.0;
for(int i = 0; i < length; i++)
{
   if(data[i] > max)
   {
      max = data;
   }
}

我尝试使用SSE3指令集对其进行向量化,但是我不知道如何进行比较。

int length = 2000;
float *data;
// data is allocated and initialized

float max = 0.0;
// for time being just assume that length is always mod 4
for(int i = 0; i < length; i+=4)
{
  __m128 a = _mm_loadu_ps(data[i]);
  __m128 b = _mm_load1_ps(max);

  __m128 gt = _mm_cmpgt_ps(a,b);

  // Kinda of struck on what to do next
}

有人能给出一些关于它的想法吗?


1
如果我们看一下代码的实际含义,我们会发现它与https://dev59.com/RWkw5IYBdhLWcg3wdKUv相同。 - John Zwinck
1个回答

11

您的代码在浮点数固定长度数组中找到了最大值。好的。

有 _mm_max_ps,它可以从两个包含四个浮点数的向量中给出成对的最大值。那么这样怎么样?

int length = 2000;
float *data; // maybe you should just use the SSE type here to avoid copying later
// data is allocated and initialized

// for time being just assume that length is always mod 4
__m128 max = _mm_loadu_ps(data); // load the first 4
for(int i = 4; i < length; i+=4)
{
  __m128 cur = _mm_loadu_ps(data + i);
  max = _mm_max_ps(max, cur);
}

最后,在max中找到四个值中的最大值(参见使用SSE获取__m128i向量中的最大值?)。

它应该按以下方式工作:

第1步:

[43, 29, 58, 94] (this is max)
[82, 83, 10, 88]
[19, 39, 85, 77]

步骤2:
[82, 83, 58, 94] (this is max)
[19, 39, 85, 77]

步骤2:
[82, 83, 85, 94] (this is max)

不客气。完成后我很想看到一些基准测试结果。 :) - John Zwinck
@JohnZwinck:“我很想看到你完成后的一些基准测试结果。”这可能会带来不好的意外,因为SSE中的非对齐移动是你可以做的最糟糕的操作之一。 - Christian Rau
1
@Christian:在最近的英特尔CPU(例如Core i3,i5,i7)上,未对齐的加载并不是一个很大的问题。 - Paul R
是的,仍然存在一些小惩罚,因此最好尽可能避免不对齐的加载,但与旧CPU上发现的不对齐的加载相比,没有2倍或更大的性能成本。 - Paul R
@ChristianRau:这并不会太出乎意料——请注意我代码中关于尽可能避免加载的注释。 - John Zwinck
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接