热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在C++中使用short(int16)进行饱和

如何解决《在C++中使用short(int16)进行饱和》经验,为你挑选了1个好方法。

我正在优化瓶颈代码:

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(sum);

我想将饱和条件写为一个"if condition",或者甚至更好,没有"if condition"来使这段代码更快.我不需要精确饱和值为32000,任何类似的值如32768都是可以接受的.

根据此页面,ARM中有一个饱和指令.在x86/x64中有类似的东西吗?



1> Jerry Coffin..:

我完全不相信试图消除这些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);,但这会产生相同的序列,并且源码似乎不太可读,至少对我而言.

如果你使用英特尔的向量指令,你可以做得比这更好,但可能只有你愿意投入大量的工作 - 特别是你可能需要对整个(小)向量进行操作通过这种方式同时实现价值观.如果你这样做,你通常会想要采取一种与你现在所采取的方法不同的方法.现在,你显然依赖于int32位类型,所以你在32位类型上进行算术运算,然后将其截断回到(饱和的)16位值.

对于像AVX这样的东西,你通常想要使用一个指令_mm256_adds_epi16来获取16个值(每个16位)的向量,并同时对所有这些值进行饱和加法(或者同样地,_mm256_subs_epi16做饱和度减法) ).

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

如果您可以依靠当前的处理器(支持AVX 512指令的处理器),您可以使用它们来同时操作32个16位值的向量.


推荐阅读
author-avatar
多米音乐_34281398
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有