问题标签 [cache-locality]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
linux - _mm_clflush 真的刷新缓存吗?
我试图通过编写和运行测试程序来了解硬件缓存的工作原理:
我使用和不使用 运行代码_mm_clflush
,而结果只是显示_mm_clflush
第一次内存访问速度更快。
与_mm_clflush
:
无 _mm_clflush
:
刷新缓存行是没有意义的,但实际上变得更快?谁能解释为什么会这样?谢谢
----------------进一步实验-------------------
假设 3899 个周期是由 TLB 未命中引起的。为了证明我对缓存命中/未命中的了解,我稍微修改了这段代码来比较L1 cache hit
和情况下的内存访问时间L1 cache miss
。
这一次,代码跳过高速缓存行大小(64 字节)并访问下一个内存地址。
由于我的电脑有一个8路组的关联L1数据缓存,有64组,总共32KB。如果我每 64 个字节访问一次内存,它应该会导致所有缓存未命中。但似乎已经缓存了很多缓存行:
这是由预取引起的吗?还是我的理解有问题?谢谢
java - 如何使用 JMH 对随机访问进行基准测试?
我试图通过对带有 JMH 的数组的顺序/随机读取进行基准测试来观察 CPU 缓存空间局部性的影响。有趣的是,结果几乎相同。
所以我想知道,这是正确的 JMH 方法吗?
下面是我用过的测试类
更新: 原来 N 太小了(1_000 * 4 bytes/int ~= 4KB)很可能整个数组都被缓存了。将 N 增加到 1_000_000 会产生更直观的结果:
memory - 了解 mips 代码中的数据缓存局部性
我一直在浏览stackoverflow,找不到关于这个的例子。我了解数据缓存的时间和空间局部性的概念:
时间地点:重新访问地址
空间局部性:每次
x
内存访问都会受到打击
但是在 mips 代码中它看起来如何呢?谁能给出具体的例子并展示它是如何工作的?
c - 动态内存分配中填充的重要性
我正在尝试实现一个堆(带有页眉/页脚的隐式空闲列表)并决定是否应该向它添加填充。添加焊盘的实际好处是什么?我读到它以某种方式减少了碎片,但我真的不明白为什么会这样。此外,我感兴趣的是我可以在时间方面获得什么样的性能优势。
这是否也有助于我的程序中的本地化,它有什么帮助?
我应该将整个块填充为 4 或 8 字节倍数的格式,还是应该填充我的块,不包括页眉和页脚。
忘了提到这是在 linux 中使用 unistd 的 C 实现。
apache-spark - 在 Apache Spark 中,如何使任务始终在同一台机器上执行?
在最简单的形式中,RDD 只是链式计算的占位符,可以任意安排在任何机器上执行:
显然可以通过使任何上游 RDD 持久化来覆盖此行为,这样 Spark 调度程序将最大限度地减少冗余计算:
现在我的问题是:
我不喜欢 vanilla 缓存机制(请参阅这篇文章:在 Apache Spark 中,我可以增量缓存 RDD 分区吗?)并编写了自己的缓存机制(通过实现新的 RDD)。由于新的缓存机制只能从本地磁盘/内存中读取现有值,如果有多个执行器,每次在另一台机器上的任务中执行分区时,我对每个分区的缓存都会经常丢失。
所以我的问题是:
如何模仿 Spark RDD 持久实现来要求 DAG 调度程序强制/建议位置感知任务调度?没有实际调用该.persist()
方法,因为它是不必要的。
valgrind - 检测缓存行是否由于空间或时间局部性而被重用
是否有实用的工具来检测是否由于空间或时间局部性而重用缓存行(避免缓存未命中)?
我在cachegrind中找不到相关讨论。我只能找到这篇论文和这篇论文,但找不到其中介绍的工具。
caching - 缓存位置注意事项
我一直在努力更好地了解缓存位置。我制作了 2 个代码片段,以更好地了解两者的缓存位置特征。
对比
在第一个代码v1
中,直接在 if 语句中进行更新。这是否会导致缓存局部性问题,因为在更新期间它将用一些连续的数据段替换当前缓存行v1[i] to v1[cache_line_size/double_size]
?如果这个分析是正确的,那么这似乎会减慢循环的速度j
,因为对于循环的每次迭代j
,它都可能有缓存未命中。似乎第二个实现通过使用局部变量并且v1[i]
在j
循环完成之前不更新来缓解这个问题?
在实践中,我认为编译器可能会优化缓存位置问题?为了讨论,我们假设没有编译器优化怎么样。
algorithm - 通过进行局部线性搜索来提高二分搜索的缓存局部性?
由于内存的随机访问,排序数组的二进制搜索可能具有较差的缓存局部性,但对于大型数组,线性搜索很慢。是否可以设计混合算法?例如,您可以将一个长度为 100 的排序数组分成 10 个块,每个块的长度为 10。在每个块中,我进行简单的线性搜索,但在“全局”级别上,我进行传统意义上的二分搜索:如果搜索到的值不在第 1 块或第 10 块中,我将查看中间,即第 5 块(因为 5 = floor((1+10)/2)。如果第 5 块不包含搜索到的值,我将查看第 3 块或第 7 块,这取决于搜索的值是小于还是大于第 5 块中的数字。
人们有没有考虑过这种算法?是否值得付出努力?
c - 确定块矩阵乘法的最佳块大小
我正在尝试在单个处理器上实现阻塞(平铺)矩阵乘法。我已经阅读了有关为什么阻塞可以提高内存性能的文献,但我只是想问一下如何确定最佳块大小。我需要执行 C+A*B,其中 A、B、C 是相同维度的浮点方阵。3 个块应该一次放入缓存是有道理的,那么块大小应该是缓存大小除以 3 吗?或者块大小应该是别的东西吗?
最后,任何人都可以提出一种可行的实验方法来确定我正在使用的超级计算机上的最佳块大小吗?我正在使用 GCC C。
c - 在嵌套循环中访问数组时缓存未命中
所以我从我的教授那里得到了这个问题,我不知道为什么vector2
比vector1
.
假设下面的代码是有效的可编译 C 代码。
矢量2:
矢量1:
注意: INT4 表示整数大小为 4 字节。
就 CPU 规格而言:缓存大小 = 12288KB,行大小 = 64B,仅考虑与主内存交互的单个缓存。
问题
为什么vector2
运行时间比 快vector1
?为什么vector1
会有更多的缓存未命中vector2
?
我和几个同学在这方面研究了一段时间,也搞不明白。我们认为这可能是由于vector2
具有更好的空间定位性,因为内部循环不断访问数组,而在 中vector1
,一次只能访问一个元素?我们不确定这是否正确,也不确定如何将缓存行引入其中。