【问题标题】:SSE2 Saturated ArithmeticSSE2 饱和算术
【发布时间】:2015-09-23 07:47:42
【问题描述】:

我正在编写一些音频处理软件,我需要知道如何使用 SSE2 双精度指令进行饱和运算。我的值需要在 -1 和 1 之间进行标准化。是否有一种巧妙的方法可以使用 SSE2 内在函数来做到这一点,或者我是否需要 2 组 if/else 语句(每个值一个)?

【问题讨论】:

  • 你为什么还要对音频使用双精度?无论如何,在您最终转换回您正在使用的任何音频格式之前,您实际上并不需要饱和,此时您可以使用饱和包指令(如果它是整数格式)或最大/最小指令,如果你想这样做明确的。
  • 那么音频格式可以被处理为 int32、int64、float32 和 float64。我现在正好在做 float64 部分。
  • OK - 只需使用 max/min 操作 - 请参阅下面的答案...

标签: c sse simd intrinsics sse2


【解决方案1】:

要将双精度值裁剪到 -1.0 到 +1.0 的范围内,您可以使用 max/min 操作。例如。如果你有一个缓冲区,buff,N 个 double 值:

const __m128d kMax = _mm_set1_pd(1.0);
const __m128d kMin = _mm_set1_pd(-1.0);

for (int i = 0; i < N; i += 2)
{
    __m128d v = _mm_loadu_pd(&buff[i]);
    v = _mm_max_pd(v, kMin);
    v = _mm_min_pd(v, kMax);
    _mm_storeu_pd(&buff[i], v);
}

【讨论】:

  • 不错!这真的很有趣。感谢您的帮助
  • 哇...我刚刚发现了一些非常有趣的东西。所有的内在功能使它变慢。而且我用的越多越慢。仅使用原始类型(双精度)我在 1738 纳秒内完成了 500000 次加法运算。仅将 SSE2 用于添加我得到 5198 纳秒。使用上面的答案,我得到了 31888 纳秒。这对我来说毫无意义。不过看看反汇编,他们使用了 xmm 寄存器。难道是编译器在做所有事情的时候都知道如何更好地优化它吗?
  • 两种可能的解释 - (1) 您使用的是调试版本,没有优化时间(即-O0)而不是发布版本(-O3)和/或(2)您的编译器已经对标量代码进行矢量化了。
  • 我正在使用 Visual Studio 并为最大化速度进行了编译。而且我相信它正在对代码进行矢量化。
  • 如果您正在对缓冲区进行单独传递以最小/最大化它,而不是在值已经在向量寄存器中时在常规计算例程结束时进行,那将是慢点。 (尤其是如果您在大于 L2 缓存的块中工作。)我的猜测是您可能正在使用内在函数,迫使编译器存储到内存,然后加载,或类似的东西。通常让自动矢量化器做好是你最好的选择。当您需要巧妙的洗牌时,更经常需要自己使用内在函数。
猜你喜欢
  • 1970-01-01
  • 2020-02-29
  • 2011-01-23
  • 2015-10-16
  • 2017-03-03
  • 1970-01-01
  • 2016-04-25
  • 2011-05-17
  • 2017-08-23
相关资源
最近更新 更多