【问题标题】:How do I use the cache efficiently when transposing an array?转置数组时如何有效地使用缓存?
【发布时间】:2013-11-05 23:58:25
【问题描述】:

如果我有一个表示 MxN 矩阵内容的一维数组(其中最不重要的维度在内存中是连续的),我如何在转置它时充分利用缓存(放置最重要的内容连续内存中的维度)。这个问题可以改写如下;

如果我可以在读取连续内存但写入随机访问位置或从随机访问位置读取并写入连续内存之间进行选择,所有条件都相同,我应该选择哪个?

【问题讨论】:

  • 不在答案中,因为我还没有实际测试过这个(有趣的问题),但如果我要与平台无关并且必须选择,我会连续写。大多数都有某种形式的写入组合,可能值得利用。
  • 选择一个基准.. 确保它在适当接近最终目标的环境中运行。这个问题在编写时确实有很多猜测,但是 如果 包含基准(和代表性代码),那么它可能是一个好问题 - 也就是说,可以查看特定的代码和特定的环境。
  • @user2864740 好的,我没有意识到这个问题会如此依赖于平台/实现。当我回到家时,我会尝试用准确的代码更新(对不起,我宁愿把头埋在马桶里,也不愿从 iPad 上引用代码)

标签: c++ caching


【解决方案1】:

只有一种通常正确的方法:编码、配置文件、测量和比较。

例如:你需要实际转置数组吗?或者将其转置就足够了(在这种情况下,迭代器可以解决问题)。很多时候,当我与我最喜欢的敌人(Fortran)互动时,我不得不“阅读转置”,因为傻瓜是专栏专业的。

Play with Eigen,可让您指定存储顺序。

但是——再一次——测试看看。我们可能会遇到这样的情况,即您正在追求红鲱鱼,而性能上的差异不会让您花时间使代码复杂化。

【讨论】:

  • 很好的答案,但我喜欢在分析每个角落和缝隙之前了解结果。有时,做学术是件好事,尽管它可能并非在每种情况下都具有实际意义。
  • 我并不反对成为“学术”。恰恰相反。而且我也喜欢了解事物的“为什么”。这就是为什么当我怀疑时,我首先测量,然后观察,然后陈述假设,然后尝试证明或反驳。众所周知,即使是专家在猜测性能方面也很糟糕。总是测试。
【解决方案2】:

如果我必须选择一个,我会选择读取连续而不是写入连续。原因

  1. 在多处理器系统中,当多个处理器同时在此数据结构上运行时,写入期间会有cache invalidation,而缓存在读取期间更有用。所以在某种程度上,缓存友好的读取比写入更有益,因为它也可以在处理器之间共享(或者在 NUMA 的情况下)
  2. 许多磁盘在磁盘控制器级别缓冲写入并将写入合并到磁盘以最大化吞吐量,因此其中的一些优化可能会自动帮助写入。

当然,因为这里有很多假设,并且取决于您的具体用例和硬件,所以您可能必须自己分析一下,看看这些声明的有效性。

【讨论】:

  • 这是我的想法,直到 Cory Nelson 提到 write combine 来证明完全相反的答案是正确的。现在我很困惑。我想分析是这个问题的答案,虽然我希望有一个相对独立于平台的答案!
  • 要考虑的另一件事是哪个操作更频繁地进行读取或写入。你是对的,连续写入是理想的,但如果你必须选择一个,那么你必须放弃另一个权利:)。现在我选择读取是因为缓存友好读取有助于所有并行读取器,而缓存友好写入仅有助于处理器写入。不过,所有这些都会慢慢进入微优化领域。
猜你喜欢
  • 1970-01-01
  • 2018-01-02
  • 2020-12-21
  • 1970-01-01
  • 2013-03-31
  • 1970-01-01
  • 1970-01-01
  • 2015-01-21
  • 2019-09-25
相关资源
最近更新 更多