3

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

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

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

我不剥皮有几个原因:

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

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

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

4

1 回答 1

5

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

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


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

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

  1. 信号 NaN
  2. 非规范化值

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

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

而且您真的不想弄乱非规范化的浮点数。

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

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


建议:

  • 零初始化数据。如果它太昂贵,至少将端点初始化为零。
  • 通过放入清理代码来避免访问未初始化的数据。像达夫的设备这样的东西可能是合适的。虽然我通常更喜欢一组二进制减少 if 语句。
于 2012-08-14T00:48:48.500 回答