STREAM Benchmark及其操作性能分析
- void tuned_STREAM_Copy()
- {
- int j;
- for (j=0; j<N; j++)
- c[j] = a[j];
- }
- void tuned_STREAM_Scale(double scalar)
- {
- int j;
- for (j=0; j<N; j++)
- b[j] = scalar*c[j];
- }
- void tuned_STREAM_Add()
- {
- int j;
- for (j=0; j<N; j++)
- c[j] = a[j]+b[j];
- }
- void tuned_STREAM_Triad(double scalar)
- {
- int j;
- for (j=0; j<N; j++)
- a[j] = b[j]+scalar*c[j];
- }
Copy操作最为简单,它先访问一个内存单元读出其中的值,再将值写入到另一个内存单元。
Scale操作先从内存单元读出其中的值,作一个乘法运算,再将结果写入到另一个内存单元。
Add操作先从内存单元读出两个值,做加法运算, 再将结果写入到另一个内存单元。
Triad的中文含义是将三个组合起来,在本测试中表示的意思是将Copy、Scale、Add三种操作组合起来进行测试。具体操作方式是:先从内存单元中中读两个值a、b,对其进行乘加混合运算(a + 因子 * b ) ,将运算结果写入到另一个内存单元。
下面展示用大页面和不用大页面测试STREAM的一组结果,然后再对结果进行简单分析。
测试平台:龙芯3A,主频UNKNOWN,大页面大小16M
测试结果:
首先看小页面模式(i.e. 普通的4K页面大小模式),Add > Copy > Triad > Scale,这是为什么?一次Add操作需要访问三次内存(两个读操作,一个写操作),Triad操作也需要三次访问内存,Copy和Scale操作需要两次访问内存。单位操作内,访问内存次数越多,越能够掩盖访存延迟,带宽越大。单位操作内,操作越复杂,操作完成时间越长,导致整个操作循环完成的时间越长。Add操作简单且访存次数多,故而带宽最大,Scale操作复杂且访存次数少,故而带宽最小。Copy操作简单但访存次数少,Triad操作复杂但访存次数多,考虑到编译器循环展开的作用,Copy操作能够更快地执行,最终导致Copy带宽比Triad略大。
大页面模式下,基本规律一致。由于使用了大页面,每访问16M页面才会出现一次物理缺页,相比每访问4K页面就出现一次缺页来说,访存缺页的概率大大降低。这里需要注意的是,TLB缺失开销在本实验中是无法观测到的。这是因为,本测试中,缺页开销占主导地位,访问过的内存不会被重新访问(时间局部性几乎没有),TLB缺失开销几乎可以不计。
STREAM Benchmark下载地址:http://www.cs.virginia.edu/stream/FTP/Code/
延伸内容:
以上分析基于STREAM1.0,现在已经推出了STREAM2.0测试,总体思想一致,四种操作进行了少许修改:
STREAM2 is an attempt to extend the functionality of the STREAM benchmark in two important ways:
- STREAM2 measures sustained bandwidth at all levels of the cache hierarchy, and
- STREAM2 more clearly exposes the performance differences between reads and writes
STREAM2 is based on the same ideas as STREAM, but uses a different set of vector kernels:
- FILL: similar to bzero(), but fills with a constant instead of zero
- COPY: similar to bcopy(), and the same as STREAM Copy
- DAXPY: similar to STREAM Triad, but overwrites one of the input vectors instead of writing results to a third vector
- SUM: sum reduction on a single vector -- reads only, no writes
Table 1: Characteristics of the STREAM2 kernels. The value in parentheses in the "Bytes/iter read" column indicates the number of additional bytes read per iteration on machines with a "write allocate" cache policy.