【问题标题】:Copy large array or change access index复制大数组或更改访问索引
【发布时间】:2016-10-04 09:12:51
【问题描述】:

抱歉,如果这个问题有一个明显的答案,但我无法正确地表达它以在网上找到答案。

在 Fortran 中,假设我有一个实数数组 (>100,000)。在时间积分方案的一个步骤中,我将不断地(以连续的方式)不断地访问这个数组。每个后续步骤将不再需要此数组的某些元素。我不知道有多少,可能从没有到全部。我的问题是:

最好是:(1) 每一步都遍历这个数组并将我需要的剩余元素复制到一个新数组中,即使可能只需要取出很小的百分比,或者 (2) 我应该有一个新的整数索引数组,我每个时间步都会更新它以访问该数组。我的理解是,如果内存访问是连续的,它应该非常快,我认为这应该超过复制数组的成本。另一方面,更新整数索引会非常快,但代价是数据会被碎片化并且访问它会更慢。

或者这是没有明确答案的问题类型,我需要去测试这两种方法以找出哪种方法更适合我的应用程序?

【问题讨论】:

  • 展示真实的代码总是比仅仅用文字描述要好。它太长,太无聊,太模棱两可。 (TLDR)
  • 我怀疑这里的答案确实是试试看。根据我的经验,使用查找数组进行索引可能会导致性能显着下降。另一种方法是实现一个链接列表,您可以在删除元素时对其进行更新,但是我怀疑这也会导致性能下降——但我认为这确实取决于您的具体用例。

标签: arrays performance fortran


【解决方案1】:

很难事先说,所以简单的答案确实是*“测量!”
不过,一些推测可能有助于衡量什么。假设代码确实对性能至关重要。

内存延迟:
100k 个元素通常会超过 L1 和 L2 缓存,因此内存局部性将发挥作用。 OTOH,线性扫描比分散访问好得多。

如果内存延迟与每个元素的操作相比显着,并且大多数元素在给定次数的迭代后变得“无趣”,我的目标是:

  • 将单个元素标记为“将在未来的迭代中跳过”
  • 当约 50% 的元素变为可跳过时,压缩内存(即删除可跳过的元素)

(测试上述条件:对于一个简单的实现,单次迭代的时间是否会随着元素数量的增加而超过线性增长?)

缓存友好块:
如果内存延迟是一个问题并且可以将多个操作应用于一个小块(比如说,32KiB 的数据),这样做。

并行化:
(房间里的大象)。如果您可以在缓存友好的块中处理,则可以轻松添加。

【讨论】:

  • 我非常喜欢标记元素然后在达到阈值后进行清理的想法。这似乎是两全其美!
  • 很想看看结果,是否有什么不同等等!
猜你喜欢
  • 2023-03-08
  • 2010-09-09
  • 2013-11-13
  • 2016-08-20
  • 1970-01-01
  • 2016-08-31
  • 1970-01-01
  • 2013-09-27
  • 2023-03-12
相关资源
最近更新 更多