c++ - C++中的饱和短(int16)

标签 c++ compiler-optimization micro-optimization

我正在优化瓶颈代码:

int sum = ........
sum = (sum >> _bitShift);

if (sum > 32000)
    sum = 32000; //if we get an overflow, saturate output
else if (sum < -32000)
    sum = -32000; //if we get an underflow, saturate output

short result = static_cast<short>(sum);

我想将饱和条件写成一个“if condition” 或什至没有“if condition” 以提高代码速度。我不需要恰好在值 32000 处的饱和度,任何类似的值(如 32768)都是可以接受的。

根据this page ,ARM中有一条饱和指令。在 x86/x64 中有类似的东西吗?

最佳答案

我完全不相信尝试消除 if 语句可能会带来任何真正的好处。快速检查表明给定此代码:

int clamp(int x) {
    if (x < -32768)
        x = -32768;
    else if (x > 32767)
        x = 32767;
    return x;
}

...gcc 和 Clang 都产生这样的无分支结果:

clamp(int):
  cmp edi, 32767
  mov eax, 32767
  cmovg edi, eax
  mov eax, -32768
  cmp edi, -32768
  cmovge eax, edi
  ret

您可以执行类似x = std::min(std::max(x, -32768), 32767); 的操作,但这会产生相同的序列,并且源代码似乎不太可读,至少对我而言。

如果您使用 Intel 的 vector 指令,您可以做得比这好得多,但可能前提是您愿意在其中投入大量工作——特别是,您可能需要对整个 (小)值 vector 同时以这种方式完成很多事情。如果你真的这样做了,你通常会想采取一种与你现在似乎正在采取的方法有所不同的方法来完成这项任务。现在,您显然依赖于 int 是 32 位类型,因此您正在对 32 位类型进行算术运算,然后将其截断为(饱和的)16 -位值。

对于像 AVX 这样的东西,您通常希望使用像 _mm256_adds_epi16 这样的指令来获取一个包含 16 个值(每个 16 位)的 vector ,并对所有这些值进行饱和加法一次(或者,同样地,_mm256_subs_epi16 进行饱和减法)。

由于您正在编写 C++,我上面给出的是用于 x86 处理器的大多数当前编译器(gcc、icc、clang、msvc)中使用的编译器内部函数的名称。如果您直接编写汇编语言,则指令分别为 vpaddsw 和 vpsubsw。

如果您可以指望真正最新的处理器(支持 AVX 512 指令的处理器),您可以使用它们来同时对 32 个 16 位值的 vector 进行运算。

关于c++ - C++中的饱和短(int16),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51959852/

相关文章:

haskell - 有哪些可能的 Haskell 优化键?

c++ - C++11 编译器在代码优化期间是否可以将局部变量转换为右值?

c++ - 重复文字和硬编码

java - ' ... != null' 还是 'null != ....' 性能最好?

c++ - 分支? : operator?

c++ - 在 C++ 字符串中替换的最佳方法是什么?

c++ - 为什么我不能调用 'explicit C(const C&)'?

c++ - 迭代过程命名

c++ - boost::python - 如何通过引用/指针传递给 python 覆盖类函数

java - 编译器是否优化了同一语句中对同一方法的多次调用?