stream benchmark 介绍

英文原版 https://www.cs.virginia.edu/stream/ref.html

FAQ中有关于STREAM_ARRAY_SIZE NTIME OFFSET STREAM_TYPE的设置说明

在stream.c的源码中也有。

最近由于工作需要,接触到Stream benchmark。Stream benchmark是一个测试内存带宽的基准测试程序。官方提供C和fortran两个版本,鉴于如今C语言使用的广泛形,本文仅从C语言版本的测试进行分析。关于Stream benchmark 的相关文档请查看https://www.cs.virginia.edu/stream/
1. 下载。要运行Stream benchmark, 首先需要下载。下载基准测试程序请移步https://www.cs.virginia.edu/stream/FTP/Code/。如果是使用C,你只需要下载一个文件stream.c。

2. 编译。如果是C程序源码,你可以使用gcc或g++进行编译。编译使用
 

                                          gcc -O stream.c -o stream_exe
    你也可以加入openmp编译选项进行多核访存带宽的测试,加入openmp选项的编译使用
                                gcc -O -fopenmp stream.c -o stream_omp_exe
    本程序有三个重要参数需要设置,他们是STREAM_ARRAY_SIZE,NTIMES以及OFFSET。关于这三个参数的含义和设置规则我将在下文详细介绍。设置这三个参数的方法有两种,一是直接在源文件中修改,二是在编译选项中加入编译规则,即使用-D 选项定义。如要定义STREAM_ARRAY_SIZE为100M,NTIMES为12以及OFFSET为2,则使用以下编译方法
    gcc -O -fopenmp -DSTREAM_ARRAY_SIZE=100000000 -DNTIME=12 -DOFFSET=1022 stream.c -o stream_omp_exe
    如果设置的STREAM_ARRAY_SIZE太大(大于2G),你可以增加编译选项-mcmodel=medium,如果继续增大这个size,可以进一步使用-mcmodel=large。除此之外,你还可以定义STREAM_TYPE,默认是double,基本不许要修改。

3. 运行及结果分析。直接使用./stream_omp_exe即可运行,如果多线程并未启动,可在运行前手动设置运行的进程数,如export OMP_NUM_THREADS=20。以下是某Power机器上的运行结果
                         -------------------------------------------------------------
                         STREAM version $Revision: 5.10 $
                         -------------------------------------------------------------
                         This system uses 8 bytes per array element.
                         -------------------------------------------------------------
                         Array size = 100000000 (elements), Offset = 0 (elements)
                         Memory per array = 762.9 MiB (= 0.7 GiB).
                         Total memory required = 2288.8 MiB (= 2.2 GiB).
                         Each kernel will be executed 10 times.
                          The *best* time for each kernel (excluding the first iteration)
                          will be used to compute the reported bandwidth.
                         -------------------------------------------------------------
                         Number of Threads requested = 20
                         Number of Threads counted = 20
                         -------------------------------------------------------------
                         Your clock granularity/precision appears to be 1 microseconds.
                         Each test below will take on the order of 13857 microseconds.
                            (= 13857 clock ticks)
                         Increase the size of the arrays if this shows that
                         you are not getting at least 20 clock ticks per test.
                         -------------------------------------------------------------
                         WARNING -- The above is only a rough guideline.
                         For best results, please be sure you know the
                         precision of your system timer.
                         -------------------------------------------------------------
                         Function    Best Rate MB/s  Avg time     Min time     Max time
                         Copy:          134965.4     0.012672     0.011855     0.013730
                         Scale:         132362.0     0.013659     0.012088     0.017100
                         Add:           141218.4     0.018251     0.016995     0.019597
                         Triad:         136666.8     0.018566     0.017561     0.019594
                         -------------------------------------------------------------
                         Solution Validates: avg error less than 1.000000e-13 on all three arrays
                         -------------------------------------------------------------
上述结果已经很清晰显示各种信息了,在这里不赘述。下面着重讲一下4个操作Copy,Scale,Add和Triad。
Copy为最简单的操作,即从一个内存单元中读取一个数,并复制到另一个内存单元,有2次访存操作。
Scale是乘法操作,从一个内存单元中读取一个数,与常数scale相乘,得到的结果写入另一个内存单元,有2次访存。
Add是加法操作,从两个内存单元中分别读取两个数,将其进行加法操作,得到的结果写入另一个内存单元中,有2次读和1次写共3次访存。
Triad是前面三种的结合,先从内存中读取一个数,与scale相乘得到一个乘积,然后从另一个内存单元中读取一个数与之前的乘积相加,得到的结果再写入内存。所以,有2次读和1次写共3次访存操作。
从上述的结果我们可以看出,测试的内存带宽Add>Triad>Copy>Scale。这是因为访存次数越多,内隐藏的访存延迟越大,得到的带宽越大。同理,运算的操作越复杂,操作时间就越长,程序运行时间就越长,得到的访存带宽就相应减少。这就是为什么3次访存的操作得到的带宽比2次访存操作得到的要大,而相同访存次数的操作,加法要比乘法得到的结果要好。

4. 参数含义及设置规则。
    1)STREAM_ARRAY_SIZE。这个是测试数据集的大小,该大小应该遵循以下两条规则。
        A. 数据集大小应不小于L3 cache大小的4倍。举例来说某10核Power机器中L3 cache为8MB/core,共80MB L3 cache,因此数据集的大小至少为80MB*4=320MB。由于数据集中每个元素大小为64bits,即8B。故,数据集大小应设置为不小与320MB/8B=40M (40million或40000000)。
        B. 数据集大小应能确保程序输出时间大于20个时钟周期。该时钟周期可在程序输出信息中看到,如“Your clock granularity/precision appears to be 1 microseconds.“ 表示时钟周期为1微秒,20个时钟周期为20微秒。如果你的测试机器有200GB/s的带宽,那你的数据集大小应不小于4MB,即0.5million个元素。
    2) NTIME。该参数为kernel执行的次数,程序将输出除第一次外其他结果中最好的结果,所以NTIME必须要大于1。该值默认为10,通常不许要修改。
    3)OFFSET。该值为数组的偏移量,修改此值可改变数组的对齐,从而在一定程度上改变输出的性能结果。一定程度在这指的是也许会改变,也许不会改变。本人在Power上的测试是没有很大的改变。如果需要修改该参数,通常将其设置为靠近2^n的数,例如使用-DOFFSET=1022 (靠近2^10=1024)。
    4) STREAM_TYPE。我们可以通过修改该参数设置测试集的数据类型,默认是double(8B)。如果将其改为float则数据集大小减少一半。

Stream benchmark已经推出stream2.0版本,相关资料及源码下载请参考https://www.cs.virginia.edu/stream/stream2/。最后感谢John和McCalpin提供这么简单粗暴方便有效的测试方式。
 
原文地址:https://www.cnblogs.com/idyllcheung/p/11282749.html