【问题标题】:Fastest method for checking overflow? [duplicate]检查溢出的最快方法? [复制]
【发布时间】:2009-03-24 13:36:03
【问题描述】:

这是我的尝试。关于更好的解决方案的任何提示?:

// for loop to convert 32 to 16 bits
uint32_t i;
int32_t * samps32 = (int32_t *)&(inIQbuffer[0]);
int16_t * samps16 = (int16_t *)&(outIQbuffer[0]);
for( i = 0; i < ( num_samples * 2/* because each sample is two int32 s*/ ); i++ ) {
    overflowCount += ( abs(samps32[i]) & 0xFFFF8000 ) ? 1 : 0; 
    samps16[i] = (int16_t)samps32[i];
}

// Only report error every 4096 accumulated overflows
if( ( overflowCount & 0x1FFF ) > 4096 ) {
    printf( "ERROR: Overflow has occured while scaling from 32 "
            "bit to 16 bit samples %d times", 
            overflowCount );
}

这是实际检查溢出的部分:

overflowCount += ( abs(samps32[i]) & 0xFFFF8000 ) ? 1 : 0; 

【问题讨论】:

  • 我们正在将 int32_t 转换为 int16_t。
  • 只想提一下:“根据您的编辑 (stackoverflow.com/revisions/677427/list),您几乎使我的整个帖子无效。感谢您在问题中未提及您的编辑。”
  • 因为您的编辑令人困惑且无益而被否决。
  • Phresnel 你在我编辑问题时做出了回答。

标签: c performance optimization embedded


【解决方案1】:

我个人更喜欢使用 SafeInt 类来进行溢出检查。它减少了对繁琐的错误检查的需求,并将其转变为易于处理但难以忽略的异常。

http://blogs.msdn.com/david_leblanc/archive/2008/09/30/safeint-3-on-codeplex.aspx

【讨论】:

    【解决方案2】:

    你已经做的,最接近单次施法的最快速度。但是你可以省略一些代码

    overflowCount += ( abs(samps32[i]) & 0xFFFF8000 ) ? 1:0;

    可以改成:

    if (samps32[i] & 0xFFFF8000) 溢出计数++;

    甚至更简单

    if (samps32[i] >> 15)overflowCount++;

    这两个速度都一样快,而且都比你的快。

    如果您实际上对溢出计数感兴趣,您可以考虑使用 SIMD 操作处理整数数组。

    【讨论】:

    • 它们不一定更快。 OP 的三元运算非常简单,可以优化为编译器的条件移动,您的两种选择都可以。即使没有可用的 cmove,由于条件分支,您的代码仍然可能执行更差...
    • ... 而三元运算更容易转化为查找表查找。
    • 不需要条件分支,编译器可以使用setz等指令。
    • phresnel 它们更快的原因不仅是因为速记条件表达式,还因为对 abs() 的调用已被删除,并且使用的是增量而不是加法。并且使用查找表只是一个巨大的开销。
    【解决方案3】:

    您似乎正在检查 16 位加法是否溢出。您可以避免在汇编代码中出现分支

    overflowCount += (samps32[i] & 0x8000) >> 15;
    

    这会生成三个 ALU 操作,但代码中没有分支。它可能会也可能不会比分支版本更快。

    【讨论】:

      【解决方案4】:

      Bit ops 也是我的选择。目前我能想象的唯一更快的方法是使用内联汇编来加载源操作数,在芯片上制作副本,截断和按位比较(那是伪伪代码)。

      您的代码存在问题:它违反了别名规则。你可以改用这样的东西:

      union conv_t {
          int32_t i32;
          int16_t i16;
      };
      

      然后您可以确保 IQBuffer 属于该类型。最后,您可以运行:

      for( i = 0; i < (num_samples * 2); i++ ) {
          <test goes here>
          samps [i].i16 = static_cast<int16_t>(samps [i].i32);
      }
      

      编辑:根据您的编辑 (https://stackoverflow.com/revisions/677427/list),您几乎使我的整个帖子无效。感谢您没有在问题中提及您的编辑。

      【讨论】:

        猜你喜欢
        • 2014-01-02
        • 2020-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-08
        • 1970-01-01
        • 2011-11-08
        相关资源
        最近更新 更多