python - 如何在python中取消优化内存访问?
问题描述
这可能没有用。这只是我为自己设定的挑战。
假设您有一个大数组。你能做些什么来使程序不能从缓存、缓存行预取或下一次内存访问只能在第一次访问完成后确定的事实中受益。
所以我们有我们的数组:
array = [0] * 10000000
如果您必须访问循环中的所有元素,那么取消优化内存访问的最佳方法是什么?想法是尽可能增加每个内存位置的访问时间
我不是在寻找一个建议在进行下一次访问之前做“其他事情”(这需要时间)的解决方案。这个想法实际上是尽可能地增加访问时间。我想我们必须以某种方式遍历数组(也许是随机的?我还在研究它)
解决方案
我没想到有任何区别,但实际上以随机顺序访问数字比按顺序或反向访问数字要慢得多(两者大致相同)。
>>> N = 10**5
>>> arr = [random.randint(0, 1000) for _ in range(N)]
>>> srt = list(range(N))
>>> rvd = srt[::-1]
>>> rnd = random.sample(srt, N)
>>> %timeit sum(arr[i] for i in srt)
10 loops, best of 5: 24.9 ms per loop
>>> %timeit sum(arr[i] for i in rvd)
10 loops, best of 5: 25.7 ms per loop
>>> %timeit sum(arr[i] for i in rnd)
10 loops, best of 5: 59.2 ms per loop
这似乎真的是随机性。只是无序访问索引,但使用模式,例如 as [0, N-1, 2, N-3, ...]
or [0, N/2, 1, N/2+1, ...]
,与按顺序访问它们一样快:
>>> alt1 = [i if i % 2 == 0 else N - i for i in range(N)]
>>> alt2 = [i for p in zip(srt[:N//2], srt[N//2:]) for i in p]
>>> %timeit sum(arr[i] for i in alt1)
10 loops, best of 5: 24.5 ms per loop
>>> %timeit sum(arr[i] for i in alt2)
10 loops, best of 5: 24.1 ms per loop
有趣的是,仅仅迭代洗牌的索引(并sum
像上面的数组一样计算它们)也比对排序的索引执行相同的操作要慢,但没有那么多。在 和 之间的约 35 毫秒差异中srt
,rnd
约 10 毫秒似乎来自迭代随机索引,而约 25 毫秒用于以随机顺序实际访问索引。
>>> %timeit sum(i for i in srt)
100 loops, best of 5: 19.7 ms per loop
>>> %timeit sum(i for i in rnd)
10 loops, best of 5: 30.5 ms per loop
>>> %timeit sum(arr[i] for i in srt)
10 loops, best of 5: 24.5 ms per loop
>>> %timeit sum(arr[i] for i in rnd)
10 loops, best of 5: 56 ms per loop
(运行 Linux 的相当旧的笔记本电脑上的 IPython 5.8.0 / Python 3.7.3)
推荐阅读
- python - 实现一个先进先出队列
- sql - 创建视图时出现重复列错误
- ios - Swift 类扩展和 Swift 类上的类别不允许有 +load 方法错误 | 在 iOS 13.3 上运行的 XCode 11.3
- laravel - 使用以前模型中的值填充 $attributes?
- javascript - 在laravel中使用javascript进行foreach循环
- android - Android 我使用 SAF 在可移动存储中保存了一张照片,但 Gallery 无法识别它并且我无法打开它
- python - 如何使用 Python 3 解决 Windows 上文件路径过长的问题?(在这个平台上尝试了其他方法)
- mips - mips汇编语言中的位屏蔽/移位?
- facebook - Starspace:labelDoc 文件格式的解释是什么?
- acumatica - 如何覆盖 JAMS 扩展