caching - Mike Acton 的面向数据设计 - 'loops per cache li

为了更好地理解 Mike Acton 关于 DOD 的演讲,我看了几次(这对我来说不是一个容易的主题)。我指的是 CppCon 2014: Mike Acton "Data-Oriented Design and C++" 和 GDC 2015: How to Write Code the Compiler Can Actually Optimize .

但在两次演讲中,他都提出了一些我感到困惑的计算:

这表明 FooUpdateIn 占用 12 个字节,但如果您堆叠其中的 32 个字节,您将获得 6 个完全打包的缓存行。 FooUpdateOut 也是如此,它占用 4 个字节,其中 32 个字节为您提供 2 个完全打包的缓存行。

UpdateFoos 函数中,您可以对每个缓存行执行 ~5.33 次循环(假设 count 确实是 32),然后他继续假设所有数学运算done 大约需要 40 个周期,这意味着每个缓存行大约需要 213.33 个周期。

这就是我困惑的地方,他不是忘记了读写吗?尽管他有 2 个完全打包的数据结构,但它们位于不同的内存空间中。 在我的脑海里,这就是正在发生的事情:

  1. 阅读in[0].m_Velocity[0](根据他之前的幻灯片,这大约需要 200 个周期)
  2. 因为 in[0].m_Velocity[1]in[0].m_Fooin[0].m_Velocity 在同一个缓存行中[0]他们的访问是免费的
  3. 做所有的计算
  4. 将结果写入 out[0].m_Foo - 这是我不知道会发生什么,我假设它会丢弃先前的缓存行(在 1. 中获取)并加载新的写结果
  5. 读取in[1].m_Velocity[0],这将再次丢弃另一个缓存行(在 4 中获取)(这将再次花费大约 200 个周期)
  6. ...

因此从inout 跳转计算从~5.33 循环/缓存行0.5 循环/缓存行 每个缓存行执行 20 个周期。

有人可以解释为什么他不关心读/写吗?还是我的想法有什么问题?

谢谢。

最佳答案

如果我们假设一级缓存为 64KB,一个缓存行为 64 字节,那么总共有 1000 个缓存行。因此,在第 4 步中写入结果 out[0].m_Foo 不会丢弃第 2 步中的数据缓存,因为它们位于不同的内存位置。这就是为什么他使用单独的结构来更新 m_Foo 而不是像在他的第一个实现中那样直接就地改变它的原因。他只是说到计算值为止。更新值(value)/写入值(value)将与他的第一个实现具有相同的成本。此外,处理器可以很好地优化循环,因为它可以并行执行多个计算(不是顺序的,因为第一个循环和第二个循环的结果不相关)。希望对您有所帮助

关于caching - Mike Acton 的面向数据设计 - 'loops per cache line' 计算正确吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63286381/

相关文章:

c++ - 使用 CMake 与网络构建 Qt 项目导致 undefined reference

azure - 从 TFS 2013 到 Azure Devops 服务的源代码迁移

c# - EpiServer DynamicDataStore LINQ 语句中的 sql 语法不正

c# - Microsoft.AspNetCore.Server.IIS.Core.IISHttpC

python - 当某些列值为空时,如何合并 Dataframe 中的多行?

angular - ionic /Angular 将对象推送到数组对象

node.js - cors 问题与 passport.js google oauth 策略

angular - 如何更新 Angular 中提供者提供的值?

.net-core - 如何停止 blazor @onclick 重新渲染页面

php - 在 Laravel 中通过表格获得一行的最佳方法是什么?