c++ - std::array 在存储大对象时是否仍然缓存友好?

标签 c++ arrays caching cpu-usage cpu-cache

<分区>

我知道 std::array 是缓存友好的,因为存储在 std::array 中的所有项目都彼此紧密相邻。如果我遍历数组,当我尝试访问一个项目时,CPU 会预取接下来的几个项目。

这就是我的困惑所在:通常 XEON 缓存行是 64 字节:即 8 个 int64_t 。成像我有

std::array<BigObject, 100> 

其中每个 BigObject 的大小为 512 字节。在那种情况下,即使所有 BigObject 项目都彼此相邻,CPU 也无法做任何聪明的事情:它仍然必须逐行获取缓存,即每个 BigObject 8 行。因此,不应该有任何缓存友好的优势。

那么我的问题是:对于大对象的std::array,是否还有缓存友好的优势?如果是这样,为什么?

最佳答案

澄清一下,处理器缓存的加速源于这样一个事实,即当今计算机的 RAM(即内存)比 CPU 慢几倍。所以 CPU 有一些小的内部存储器,称为高速缓存,速度很快。为了最好地利用小内存,CPU通常使用时间和空间的概念,意思是经常使用的东西保存在缓存中,最近使用的东西旁边的东西,它们在内存中的邻居,也被加载到缓存中,因为接下来很可能需要它们。

所以正如您所理解的那样,当事物在内存中紧密相连时,它们会被友好地缓存。由于 std::arraystd::vector 被称为 ContiguousContainer,它们在内存中将它们的内容相邻保存。

因此,将您经常使用的东西放在一起确实缓存友好,即您在循环中迭代或在这样的容器中一个接一个地使用。

如果你的对象像你说的那么大,你可以做你想做的,它们太大而无法放入缓存,以合理的数量计算。所以你要么看看你在那些对象中如此频繁地操作是什么,并且只将它存储在容器中,要么你忍受不可避免的减速。如果您首先在您使用的类或结构中定义最重要的成员,您也可以加快速度,因为这转化为成员存储在内存中的布局。类(class)成员要事第一。

但正如所有这些人所建议的,更重要的是:通常您的算法复杂性对您程序的整体运行时间更为重要。 例如:问问你自己,你的程序是否在每个大对象上做一点工作然后转到下一个,然后才对每个大对象做一些其他小工作,这是非常低效的,或者你能做所有工作吗?一次获取一个对象,然后才转到下一个大对象?如果不是,为什么你的对象这么大?它们不应该只包含手头任务所需的东西吗? 不要为了希望事情会变得更快而把事情搞得一团糟。 “过早的优化是万恶之源”是一句流行的名言就是这种语境。首先编写您的程序清晰易读且正确。然后运行它并测量它实际上很慢的地方。关于缓存实现的一般推测通常不是很有帮助,像“当有疑问时使用 vector 或数组,因为它们通常是最快的”这样的启发式就足够了。

或者为了更好地回答您的问题:std::arraystd::vector 都是缓存友好性的最佳选择,但是没有容器可以对大对象缓存友好,因为大对象由于大而对缓存不友好。

关于c++ - std::array 在存储大对象时是否仍然缓存友好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58167254/

相关文章:

java - 一维数组遇到问题

javascript - 如何检查数组是否包含至少一个对象?

python - 在 django 中需要帮助与 memcached 和 friend 一起进行中级/高级缓存

Nginx:在我的缓存中打一个洞没有按预期工作

c++ - 通过字符串模板参数访问元组

c++ - 64 位环境中的成员变量指针

mysql - MYSQL 中的 UNNEST 函数类似于 POSTGRESQL

ruby-on-rails - Scraping rake 任务似乎受到不需要的缓存的影响

c++ - 如何为自定义结构中定义的 unordered_set 编写自定义哈希函数?

c++ - 我如何编写一个 for 循环来遍历 CAtlMap 有选择地删除元素?