分割如何提高埃拉托斯尼筛的运行时间
How does segmentation improve the running time of Sieve of Eratosthenes?
我发现了一个Eratosthenes筛的分段实现,它的运行速度有望比传统版本快很多倍。有人能解释一下分段是如何提高运行时间的吗?注意,我想在[1,b]中找到素数。
它在这个想法上起作用:(用于寻找直到10^9的素数)
我们首先生成sqrt(10^9)以下的筛选素数,这些素数是划掉倍数所必需的。然后我们开始将第一素数2的倍数划掉,直到我们达到2>=的倍数segment_size,如果发生这种情况,我们使用(multiple-segment_size)计算下一个段中该倍数的索引,并将其存储在一个单独的数组中(next[])。然后,我们使用相同的程序划掉下一个筛选素数的倍数。一旦我们划掉了第一段中所有筛选素数的倍数,我们就在筛数组上迭代,并打印(或计数)素数。
为了筛选下一个片段,我们重置了筛选数组,并将较低的偏移量增加segment_size。然后我们再次开始划掉倍数,对于每个筛选素数,我们从下一个数组中检索筛选指数,然后开始划掉从那里开始的倍数…
分段筛执行与常规筛相同的所有操作,因此big-O时间复杂性不变。区别在于记忆的使用。如果筛子足够小,可以放在记忆中,那就没有区别了。随着筛网尺寸的增加,参考位置成为一个因素,因此筛分过程减慢。在极端情况下,如果筛子不适合内存,必须分页到磁盘,筛选过程将变得非常缓慢。分段筛选使内存大小保持不变,而且可能很小,因此对筛选的所有访问都是本地的,因此速度很快。
即使筛子完全适合RAM,访问的局部性仍然会产生很大的影响。只有Eratosthenes的几率的C++实现几乎需要半分钟来筛选前2^32个数字;同样的实现在256 KB的小段(2^21位,表示2^22个数字)中初始化相同的筛子,在我的老化Nehalem上只需8.5秒,它有256 KB的L2缓存。
在小缓存友好段中筛选的速度在范围的较高区域减小,因为无论段大小,筛选每次都必须迭代所有因子,直到sqrt(n)。这在接近2^64的段中最为显著,其中小因子包括203280221素数(即完整的32位筛选)。
不过,分段操作仍然胜过全面筛选。你可以筛选接近2^64的片段,每秒数百万个素数,在较低的区域每秒数千万个素数。这是在计算素数,而不是原始数矿石。即使你有很多记忆,超过2^32左右的全筛也不实用。
- KMP算法和LPS表构造的运行时间
- 如何计算Big-O表示法中的平均渐近运行时间
- 用时钟测量程序的运行时间
- 如何减少代码的运行时间以对齐文本?
- 我的 c++ 应用程序中的运行时间从 0 增加到 60 太快了(例如一毫秒或一微秒)
- 使用 Qt 测量过程的实际运行时间
- 在SQLITE数据库中写入记录需要花费大量时间.如何提高刀片操作效率?
- 如何执行用 C++ 编写的程序的运行时间?
- 无限运行时间
- 如何优化C++键值程序以获得更快的运行时间
- 这个算法的运行时间复杂度是多少?你是如何分析的
- 两个嵌套循环的运行时间复杂性:二次型还是线性
- 重复值的最长运行时间
- 同一程序的运行时间差异很大,有时达到1000+us
- 测量 OpenCL 应用程序的运行时间
- 为什么以相同的数量插入到集合中,基于不同的方法具有不同的运行时间?
- variadic函数模板:基于n编译时值在运行时间自动n输入
- 如何修复数据库连接的C 程序运行时间错误(0xc0000005)
- 比较向量元件的运行时间复杂性的提高
- 分割如何提高埃拉托斯尼筛的运行时间