【发布时间】:2018-09-04 00:18:56
【问题描述】:
在 BST 中查找元素(遍历)会比在数组中线性扫描要慢吗?
答案应该与缓存有关。有人可以解释这到底是什么意思以及为什么它是正确的吗?
您究竟是如何使用数组而不是使用 BST 缓存来“缓存这个”的?
谢谢
【问题讨论】:
标签: arrays caching tree operating-system
在 BST 中查找元素(遍历)会比在数组中线性扫描要慢吗?
答案应该与缓存有关。有人可以解释这到底是什么意思以及为什么它是正确的吗?
您究竟是如何使用数组而不是使用 BST 缓存来“缓存这个”的?
谢谢
【问题讨论】:
标签: arrays caching tree operating-system
我的猜测是,使用 BST 不会给您带来任何优势,因为即使您正在缓存数据(这意味着存在某种局部性,例如,您可以稍后访问相同的元素),插入操作并且查找操作总是花费 O(h) 其中 h 是树的高度。在最坏的情况下,甚至 O(n)。
虽然使用数组进行缓存意味着当然,起初它可能是线性的,但是当您之后访问数组的相同元素时,如果存在空间和时间局部性,您可能会发现自己直接访问相同的块连续内存重复,因为你已经知道它的索引,这意味着你有一个恒定的时间访问。
【讨论】:
我假设缓存与 CPU 缓存有关,它带有一个预取器,可以预测您的下一次内存访问。因此,如果您在数组中按顺序搜索,您的预取器会识别内存访问模式并在 CPU 访问之前将内存加载到 CPU 缓存中。当 CPU 真正访问下一个内存元素时,它已经在缓存中,可以快速访问。 如果没有缓存和预取器,您的 CPU 将不得不等待内存控制器从 RAM 中获取数据,这与 CPU 缓存相比非常慢。
在 BST 中,您不进行顺序访问。在最坏的情况下,您的 BST 不会驻留在连续内存中,但每个节点都位于内存中的某个任意位置。您的预取器无法预测这一点。然后 CPU 必须等待从内存中取出每个元素。
虽然没有预取器,但与缓存行有关。在 x86_64 上,高速缓存行的长度为 64 字节。每个整数是 4 或 8 字节,因此您可以在每个高速缓存行扫描 16 或 8 个数组条目。对内存位置的第一次访问会获取整行,因此您只需为 8 次比较支付一次内存访问。 对于 BST,与上述相同的论点也适用。节点内存可能不在同一缓存行上,因此必须为每次比较进行内存访问。
总结一下:A)内存访问比比较花费的时间要多得多; B) 搜索数组或 BST 是否更快取决于项目的数量。
【讨论】: