我对STREAM(http://www.cs.virginia.edu/stream/ref.html#runrules)基准测试有一些疑问。
* (a) Each array must be at least 4 times the size of the
* available cache memory. I don't worry about the difference
* between 10^6 and 2^20, so in practice the minimum array size
* is about 3.8 times the cache size.
例如,我添加了两个额外的数组,并确保与原始a / b / c数组一起访问它们。我相应地修改了字节记帐。有了这两个额外的阵列,我的带宽数量增加了约11.5%。
> diff stream.c modified_stream.c
181c181,183
< c[STREAM_ARRAY_SIZE+OFFSET];
---
> c[STREAM_ARRAY_SIZE+OFFSET],
> e[STREAM_ARRAY_SIZE+OFFSET],
> d[STREAM_ARRAY_SIZE+OFFSET];
192,193c194,195
< 3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE,
< 3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE
---
> 5 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE,
> 5 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE
270a273,274
> d[j] = 3.0;
> e[j] = 3.0;
335c339
< c[j] = a[j]+b[j];
---
> c[j] = a[j]+b[j]+d[j]+e[j];
345c349
< a[j] = b[j]+scalar*c[j];
---
> a[j] = b[j]+scalar*c[j] + d[j]+e[j];
CFLAGS = -O2 -fopenmp -D_OPENMP -DSTREAM_ARRAY_SIZE = 50000000
我的上一级缓存约为35MB。
有没有通讯网?
谢谢!
这是用于Skylake Linux服务器。
答案 0 :(得分:7)
现代计算机中的内存访问比人们预期的要复杂得多,并且由于某些您不知道的“低级”细节,很难说出“高级”模型何时崩溃。之前......
STREAM基准代码仅测量执行时间-其他所有内容都派生出来。得出的数字基于有关我认为“合理”的决定以及有关大多数计算机的工作原理的假设。运行规则是反复试验的产物-试图在可移植性和通用性之间取得平衡。
STREAM基准报告每个内核的“带宽”值。这些简单的计算基于以下假设:必须从内存中读取每个循环右侧的每个数组元素,并且必须将每个循环左侧的每个数组元素写入内存。那么,“带宽”就是移动的数据总量除以执行时间。
这种简单的计算涉及许多令人惊讶的假设。
有关避免“写入分配”流量的其他说明:
答案 1 :(得分:2)
正如Bandwidth博士的答案所指出的那样,关键是STREAMS仅计算源代码中可见的有用带宽。 (他是基准测试的作者。)
实际上,对于RFO(读取所有权)请求,写入流还会产生读取带宽成本。例如,当CPU要向高速缓存行写入16个字节时,首先必须加载原始高速缓存行,然后在L1d高速缓存中对其进行修改。
(除非您的编译器使用绕过缓存的NT存储自动向量化并避免了RFO。一些编译器会针对循环执行此操作,因为他们希望在缓存中的任何一个都写之前写一个更大的数组重新阅读。)
有关避免RFO的绕过缓存的存储的更多信息,请参见Enhanced REP MOVSB for memcpy。
因此,增加读取流与写入流的数量将使软件观察到的带宽更接近实际的硬件带宽。(此外,内存的混合读/写工作负载可能并不是十分有效。 )
答案 2 :(得分:1)
STREAM基准测试的目的不是测量峰值内存带宽(即,系统上可以实现的最大内存带宽),而是测量多个内核(COPY,SCALE)的“内存带宽” ,SUM和TRIAD)对HPC社区至关重要。因此,当STREAM报告的带宽更高时,这意味着HPC应用程序可能会在系统上运行得更快。
理解STREAM基准测试中“内存带宽”一词的含义也很重要,这在文档的最后一部分中进行了说明。如该部分所述,至少有三种方法可以计算基准的字节数。 STREAM基准测试使用STREAM方法,该方法计算在源代码级别读取和写入的字节数。例如,在SUM内核(a(i)= b(i)+ c(i))中,读取两个元素,并写入一个元素。因此,假设所有访问都针对内存,则每次迭代从内存访问的字节数等于数组数乘以元素大小(即8个字节)。 STREAM通过将访问的元素总数(使用STREAM方法计数)乘以元素大小,再除以内核的执行时间来计算带宽。为了考虑运行间的差异,每个内核会运行多次,并报告算术平均,最小和最大带宽。
如您所见,STREAM报告的带宽不是实际的内存带宽(在硬件级别),因此说它是峰值带宽甚至没有意义。此外,它几乎总是比峰值带宽低得多。例如,this文章显示了ECC和2MB页面如何影响STREAM报告的带宽。编写一个实际上可以在现代英特尔处理器上实现最大可能的内存带宽(在硬件级别)的基准测试是一个很大的挑战,对于整个博士来说,这可能是一个好问题。论文。但是,实际上,峰值带宽不如HPC域中的STREAM带宽重要。 (相关:有关在硬件级别测量内存带宽所涉及问题的信息,请参见my answer。)
关于您的第一个问题,请注意STREAM仅假定主存储器而不是任何缓存满足所有读取和写入操作。分配比LLC大小大得多的阵列有助于使这种情况更可能发生。从本质上讲,LLC的复杂和无证件方面,包括更换政策和安置政策,都需要克服。它不必比LLC大4倍。我的理解是,这是Bandwidth博士在实践中发现的。