我正在优化瓶颈代码:
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/