【问题标题】:Fastest use of a dataset of just over 64 bytes?最快使用超过 64 字节的数据集?
【发布时间】:2015-06-18 13:25:10
【问题描述】:

结构:我有 8 个 64 位整数(512 位 = 64 字节,假定的缓存行宽度),我想依次与另一个 64 位整数进行比较,没有缓存未命中。不幸的是,数据集绝对不灵活——它已经尽可能小了。

访问模式: 每个 uint64_t 实际上是一个 4x4x4 位的数组,每个位代表一个体素的存在或不存在。这意味着有时我会使用一个块的一半和另一个块的一半,甚至是 8 个不同的 64 位块的角......我猜这意味着很有可能缺乏对齐。

我怎样才能尽可能快地做到这一点,即不破坏缓存?

附:这个想法是,这段代码最终将在至少 64B 缓存线宽度的相当广泛的体系结构上运行,所以我希望这绝对是尽可能快的。这也意味着我不能依赖 MOVNTDQA,尽管将第 9 个元素直接加载到 CPU,但它本身可能会导致性能下降。

附言我对这方面的知识相当有限,所以请放轻松。但是请放过我过早的优化cmets;确保这是该应用程序中真正重要的 3%。

【问题讨论】:

  • 数据集通常描述整体大小 - 看起来您有 64B 个对象,但您预计其中有多少?
  • @Leeor 我总共有 9x uint64_t = 68B。出于概念目的,我考虑将另外一个与其他八个进行比较。嗯,只是考虑内存布局......见编辑。
  • 这取决于你的目标架构。

标签: c cpu-cache


【解决方案1】:

我不会担心的。如果你的数据集真的只有 9 个整数,那么大部分数据很可能会存储在寄存器中。此外,实际上没有任何方法可以在不指定架构的情况下优化缓存使用,因为缓存结构 依赖于架构。如果您可以列出几个目标架构,您可能会找到一些可以优化的共性,但在不了解这些架构的情况下,我认为我们无能为力。

最后,这似乎是过早优化的一个很好的例子。我建议您采取以下步骤:

  1. 确定您可接受的最长运行时间是多少
  2. 用 C 完成你的程序
  3. 为所有目标架构编译
  4. 对于那些不符合您的速度规范的平台,手动优化中间程序集文件并重新编译,直到您符合您的规范。

【讨论】:

  • 你提出了一些有效的观点。但是我想提醒你完整的引用:“程序员浪费大量时间思考或担心他们程序的非关键部分的速度,而这些效率上的尝试实际上在调试和维护时产生了强烈的负面影响考虑到。我们应该忘记小的效率,比如说大约 97% 的时间:过早的优化是万恶之源。但我们不应该放弃那关键的 3% 的机会。 这是最重要的 3%。 人工智能、物理、渲染都依赖于这个速度。
  • @ArcaneEngineer 我很抱歉假设您尚未完成分析以识别此代码段。我已经看到太多关于 SO 的优化问题,其中 OP 没有做任何工作来确定正确的 3%,所以我有点习惯性地回答。那是我的错误。
  • 不要显得不欣赏;感谢您的帮助,我赞成您回答中有用的部分。
  • @ArcaneEngineer 谢谢!
【解决方案2】:

你确定你得到缓存未命中? 即使比较值不在寄存器中,我认为你的第一个 uint64 数组应该在一个缓存阶段(或者它被称为什么),而你的其他数据在另一个。 您的缓存肯定有一些 n 向关联性,这可以防止您的数据行仅通过访问您的比较值就被从缓存中删除。

不要在微优化上浪费时间。改进您的算法和数据结构。

【讨论】:

  • 他没有说8个uint64在一个数组中。如果 n 小于 8 并且这 8 个整数恰好位于彼此正好为 SizeOfCacheLine*2^M 字节的地址上,则确实可能存在缓存冲突。如果它们完全随机地分散在内存中,或者像数组一样紧密地在一起,则不会发生这种情况,但可能会发生在诸如跨行大小为 SizeOfCacheLine*2^M 的图像的行之类的情况下。
猜你喜欢
  • 2021-04-06
  • 2010-10-27
  • 2020-03-11
  • 2018-07-21
  • 2017-10-09
  • 2023-03-21
  • 2021-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多