为啥较大搜索值的实际运行时间小于排序数组中的较低搜索值?

Posted

技术标签:

【中文标题】为啥较大搜索值的实际运行时间小于排序数组中的较低搜索值?【英文标题】:Why actual runtime for a larger search value is smaller than a lower search value in a sorted array?为什么较大搜索值的实际运行时间小于排序数组中的较低搜索值? 【发布时间】:2020-07-10 12:11:11 【问题描述】:

我对包含范围 [1, 10000] 中所有唯一元素的数组执行线性搜索,按所有搜索值的升序排序,即从 1 到 10000,并绘制运行时与搜索值的关系图,如下所示:

仔细分析放大版的情节如下:

我发现一些较大的搜索值的运行时间小于较小的搜索值,反之亦然

我对这种现象的最佳猜测是它与 CPU 如何使用主内存和缓存处理数据有关,但没有可靠的可量化理由来解释这一点。

任何提示将不胜感激。

PS:代码是用 C++ 编写的,并在 linux 平台上执行,该平台托管在 Google Cloud 上具有 4 个 VCPU 的虚拟机上。运行时间是使用 C++ Chrono 库测量的。

【问题讨论】:

你的定时器的精度是多少?一个简单的解释是,离散化是计时器分辨率的直接结果(以及基于环境变量(如系统负载)的预期运行时微小扰动。) 我在 C++ 中使用 Chrono 来测量运行时@ldog 【参考方案1】:

CPU 缓存大小取决于 CPU 型号,有多个缓存级别,因此您的实验应考虑所有这些因素。 L1 缓存通常为 8 KiB,比您的 10000 阵列小约 4 倍。但我不认为这是缓存未命中。 L2 延迟约为 100ns,远小于最低线和第二线之间的差异,约 5 微秒。我想这(第二行云)是由上下文切换贡献的。任务越长,上下文切换发生的可能性就越大。这就是为什么右侧的云更厚的原因。

现在是放大的图。由于 Linux 不是实时操作系统,它的时间测量不是很可靠。 IIRC 它的最小报告单位是微秒。现在,如果某个任务恰好需要 15.45 微秒,那么它的结束时间取决于它开始的时间。如果任务在精确的零时钟开始,则报告的时间将为 15 微秒。如果它在内部时钟为 0.1 微秒时开始,那么您将获得 16 微秒。您在图中看到的是模拟直线对离散值轴的线性近似。因此,您获得的任务持续时间不是实际的任务持续时间,而是实际值加上任务开始时间以微秒为单位(均匀分布 ~U[0,1])并将所有这些四舍五入到最接近的整数值。

【讨论】:

以上是关于为啥较大搜索值的实际运行时间小于排序数组中的较低搜索值?的主要内容,如果未能解决你的问题,请参考以下文章

仅当 min 位于数组的较低索引位置时才使用 .minmax 返回值

在有序数组中找到小于 x 的最大值

qsort函数sort函数

C排序(种类)

算法总结之 未排序数组中累加和小于或等于给定值的最长子数组长度

找出升序排序数组第一个小于目标值的所有下标,第一个大于目标值的所有下标——四次二分搜索