【问题标题】:Can accessing uninitialized values result in a performance hit?访问未初始化的值会导致性能下降吗?
【发布时间】:2012-08-14 00:19:19
【问题描述】:

我正在优化一个矩阵数值热点。

目前,我正在做阻塞和loop unrolling 以提高性能。但是,我故意避免剥去边框。相反,我让阻塞步骤溢出,当然,算法随后会触及未初始化的值。

但是,矩阵被慷慨地预先分配以应对溢出,所以我实际上并没有非法访问内存位置。

我不剥皮有几个原因:

  • 懒惰
  • 由于剥落边框的位置非常糟糕,性能受到影响。
  • 避免复杂的边框剥离代码。

但是,我想知道这些触及未初始化值的溢出访问是否真的会导致性能下降?

我可以预见地知道未初始化的访问发生在哪里,并且它们也通过 valgrind 报告。我还使用 Intel 的 VTune 对代码进行了概要分析,并且看不到任何表明性能下降的迹象。

【问题讨论】:

  • +1,我强烈建议您至少对它们进行零初始化。假设您正在使用浮点,未初始化的数据很可能被非规范化。 And you do not want that to mess up your performance.
  • 我知道,但是用memset 贪婪地将预先分配的矩阵池清零也非常昂贵。
  • 虽然取决于循环的大小,但每个循环结束时几百个循环的惩罚可能并不明显。
  • 您不必初始化整个数据集。只是终点。
  • 加载未初始化的值不会影响性能。但是,如果您尝试对它们进行任何算术运算,那么它肯定会受到非规范化的影响。

标签: c++ performance optimization micro-optimization initialization


【解决方案1】:

只是为了摆脱迂腐的东西:

根据标准,如果您使用未初始化的数据,可能会发生坏事。 (该标准允许可能触发异常的“陷阱”值。)但出于所有实际目的,这可能不适用于此处。


如果您正在处理整数,访问和操作未初始化的数据不会影响性能。 (除除法外,所有操作通常都是固定延迟)

对于浮点数,有两个问题:

  1. Signalling NaNs
  2. Denormalized Values

根据环境,信号 NaN 可能会触发硬件异常。所以这实际上是一个正确性问题,而不仅仅是性能问题。

非正规浮点数与此有关,这可能违反直觉。然而, 未初始化的数据很可能被非规范化。

And you really don't want to be messing with denormalized floating-point.

因此,如果您很不幸地使未初始化的值甚至具有一个非规范化值,那么在每次循环迭代结束时,您可能会遇到令人讨厌的 100 多个循环惩罚。现在取决于循环的大小,这可能重要也可能不重要。

也就是说,为什么未初始化的数据容易被非规范化?如果浮点值的前几位为零,则它被非规范化。就这么容易。如果数据曾经是一个整数,或者是一个 64 位的指针……当重新解释为浮点值时,它会被非规范化。


建议:

  • 零初始化数据。如果太昂贵,至少将端点初始化为零。
  • 通过放入清理代码来避免访问未初始化的数据。像Duff's Device 这样的东西可能是合适的。虽然我通常更喜欢一组二进制减少 if 语句。

【讨论】:

    猜你喜欢
    • 2020-10-30
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 2014-02-19
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 2011-02-13
    相关资源
    最近更新 更多