【问题标题】:Faster to use Integers as Booleans?更快地将整数用作布尔值?
【发布时间】:2011-08-20 09:00:01
【问题描述】:

从内存访问的角度来看...是否值得尝试这样的优化?

int boolean_value = 0;

//magical code happens and boolean_value could be 0 or 1

if(boolean_value)
{
   //do something
}

代替

unsigned char boolean_value = 0;

//magical code happens and boolean_value could be 0 or 1

if(boolean_value)
{
   //do something
}

与整数 4 相对的 unsigned char 当然只占用 1 个字节(假设这里是 32 位平台),但我的理解是处理器从内存中读取整数值会更快。

【问题讨论】:

    标签: c optimization


    【解决方案1】:

    这几乎不是一个好主意。许多系统一次只能从内存中读取字大小的块,因此读取一个字节然后进行屏蔽或移位实际上会占用更多代码空间和同样多的(数据)内存。如果您使用的是不起眼的微型系统,请进行测量,但通常这实际上会减慢和膨胀您的代码。

    【讨论】:

    • 自 1980 年代以来未使用的“许多”系统可能......不过,除此之外,您的建议是合理的。
    • @R:我使用 3 个符合要求的处理器,尽管它们确实非常晦涩。
    【解决方案2】:

    从内存访问的角度来看...是 值得尝试优化 像这样?

    可能不会。在几乎所有现代处理器中,内存将根据处理器的字长获取。在您的情况下,即使要取出一个字节的内存,您的处理器也可能会根据该处理器的缓存来获取整个 32 位或更多的字。您的架构可能会有所不同,因此您需要了解您的 CPU 是如何工作的。

    但正如其他人所说,尝试并衡量它并没有什么坏处。

    【讨论】:

    • 你实际上会得到一个完整的缓存行,64字节。
    • @drhirsch:你对 Doug T. 的 CPU 架构了解很多 ;-) 甚至比 Doug T. 对提问者的了解还要多……
    • 让我再试一次:在带有缓存的架构上(现在几乎所有),您将获得一个完整的缓存行(例如在当前的 amd/intel 系统上 64 字节)。顺便说一句,现在我记得一种架构,其中内存被读取的部分比处理器字更小:8088 和 68008,都是 16 位处理器,但只有 8 位内存接口。
    • @drhisch @Steve 希望我的回答足够合格:)。
    • 如果您甚至可以测量两者之间的差异,我会感到惊讶,除非其他代码非常琐碎并且该代码在特定代码中花费了大量时间。
    【解决方案3】:

    它可能会更快,也可能不会更快,而且速度取决于很多事情,以至于不可能给出通用答案。例如:硬件架构、编译器、编译器选项、数据量(是否适合 L1 缓存?)、其他争夺 CPU 的东西等。

    因此,正确的答案是:尝试两种方法并针对您的特定情况进行衡量。

    如果测量没有表明一种方法明显快于另一种方法,请选择更清晰的方法。

    【讨论】:

    • 无论如何,没有什么能阻止编译器使布尔值变大。 VS2010 和 gcc4 都在结构中扩展了我的 uint8_t 成员 - 尽管他们可能只是出于对齐原因这样做,但我不明白为什么不允许他们在这里做同样的事情。
    【解决方案4】:

    遵循优化的标准规则。首先,不要优化。然后测试您的代码是否在某个时候需要它。然后优化那个点。此链接对优化主题进行了很好的介绍。

    http://www.catb.org/~esr/writings/taoup/html/optimizationchapter.html

    【讨论】:

    • 谢谢你,一定会看看的。
    • 我原则上同意这个建议,但是你怎么知道你的程序什么时候使用了“太多”的内存呢?与性能不同,内存使用量很容易根据您的程序实际执行的操作来估算,并且大多数与您估算的偏差都会导致实施效率低下。
    • 我想我的观点是,从一开始就积极主动地不使用过多的内存是一件好事,只要您专注于程序中使用最多内存的部分。除非您拥有数百万个布尔值数组,否则 int 布尔值可能不是您最大的内存消耗之一。
    【解决方案5】:

    询问unsigned charint 占用了多少内存只有在数组中时才有意义(或者可能是一个结构,如果您小心地对元素进行排序以进行对齐) )。作为一个单独的变量,您根本不可能节省任何内存,并且编译器可能会生成更大的代码来截断寄存器的高位。

    作为一般策略,除非您有非常好的理由而不是试图节省空间,否则不要在数组中使用小于int 的类型。

    【讨论】:

    • 也许要为变量指定自然边界?
    • 如果你想依赖无符号类型的模块化归约,这是一个正当的理由——但你必须记住默认提升,直到你分配回“小类型”才会发生归约.但是,如果您使用有符号类型,则较大值的转换具有实现定义的行为,并且不会有用。无论如何,我都建议不要使用小类型。
    猜你喜欢
    • 2011-03-11
    • 1970-01-01
    • 2010-12-16
    • 2016-05-01
    • 2018-11-08
    • 1970-01-01
    • 2020-04-08
    • 1970-01-01
    • 2019-03-06
    相关资源
    最近更新 更多