c++ - 有没有办法避免这个函数中的分支/条件逻辑?

标签 c++ optimization conditional-statements

我的程序中有这个简单的函数:

enum {
   TABLE_INDEX_TYPE_UINT8 = 0,
   TABLE_INDEX_TYPE_UINT16,
   TABLE_INDEX_TYPE_UINT32,
};

// inline method
uint8_t MyTable :: GetTableIndexTypeForTableSize(uint32_t tableSize) const
{
   // Deliberately testing for strictly-less-than-255/65535 here, 
   // because 255 and 65535 are used as special sentinel values
   return (tableSize < 255) ? TABLE_INDEX_TYPE_UINT8 
        : ((tableSize < 65535) ? TABLE_INDEX_TYPE_UINT16 : TABLE_INDEX_TYPE_UINT32);
}

在我程序的当前版本中,每当 tableSize 发生变化时,我都会调用此方法,并将结果存储在一个成员变量中以供快速重用,而且效果很好。

但是,今天我正在尝试减少 sizeof(MyTable),其中一种方法是去除不必要的成员变量。由于上述函数的缓存结果始终是可重新计算的(基于 tableSize 成员变量的当前值),我修改了代码以仅调用 GetTableIndexTypeForTableSize(tableSize) 需要的时候。

这也很好用(并且允许我将 sizeof(MyTable) 减少 4 个字节,是的),但它导致我的性能基准测试中的性能下降可测量 (~5%) -- 我认为这是因为 GetTableIndexForTableSize() 的当前实现包括两个分支操作。

所以我的问题是,是否有一种聪明的方法可以重新实现上述功能,使其不需要任何分支,从而避免 5% 的减速? (我假设使用查找表是 坏主意,因为我会用 RAM 访问延迟替换分支预测错误延迟,使事情变得更慢)

最佳答案

如果您仔细选择您的枚举值,应该可以按位或您自己得到正确的枚举值。不过,我怀疑它会快得多。

#include <cstdint>
enum {
  TABLE_INDEX_TYPE_UINT8 = 0,
  TABLE_INDEX_TYPE_UINT16 = 1,
  TABLE_INDEX_TYPE_UINT32 = 3
};

uint8_t MyTable::GetTableIndexTypeForTableSize(uint32_t tableSize) const
{
  return (tableSize >= 255) | ( (tableSize >= 65535) << 1 );
}

关于c++ - 有没有办法避免这个函数中的分支/条件逻辑?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55822777/

相关文章:

c++ - std::random_device 的线程安全

c++ - Matlab 与 C++ 运行时比较

delphi - 为什么这种 RTTI 优化会使速度变慢?

狂欢 "not": inverting the exit status of a command

c++ - 数组 :/有问题

C++ 指针作为 DWORD

c - 为什么编译器生成的代码会一遍又一遍地在同一内存位置写入相同的内容?

css - 基于子元素的菜单控制CSS

android - 测试绘图和背景等资源

c++ - 下标超出范围 C++ vector 删除