本文最后更新于 2024-11-11 15:22

一 概述

内存带宽为处理器可以从内存读取数据或将数据存储到内存的速率

具体计算方式可以举例说明如下:

节点单节点理论内存带宽=3200MHz*64bit*8通道*2颗CPU/8bit/1024=400GB/s

二 编译

内存带宽一般采用stream.c程序进行编译,根据笔者的经验,Intel编译器编译得到的程序性能较优,基本上测试出来的内存带宽都在理论值的70%以上,Intel编译器安装方法可以参考https://docs.aheadai.cn/155.html

Stream的官方下载地址:http://www.cs.virginia.edu/stream/FTP/Code/stream.c

如果官方地址失效,可以使用以下地址:

wget https://mirrors.aheadai.cn/pkgs/stream.c

则编译命令为:

icc -o stream stream.c -DSTATIC -DNTIMES=10 -DSTREAM_ARRAY_SIZE=2500000000 -mcmodel=large -shared-intel -Ofast -qopenmp -ffreestanding -qopt-streaming-stores always

三 测试

测试命令为:

export OMP_PROC_BIND=true
export OMP_NUM_THREADS=64 # 这里的64是所测试节点的CPU总核心数量(建议设置为超线程之前的核心数,即物理核心数)
./stream

测试结果示例为:

-------------------------------------------------------------
STREAM version : 5.10 $
-------------------------------------------------------------
This system uses 8 bytes per array element.
-------------------------------------------------------------
Array size = 2500000000 (elements), Offset = 0 (elements)
Memory per array = 19073.5 MiB (= 18.6 GiB).
Total memory required = 57220.5 MiB (= 55.9 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 = 64
Number of Threads counted = 64
-------------------------------------------------------------
Your clock granularity/precision appears to be 1 microseconds.
Each test below will take on the order of 124275 microseconds.
   (= 124275 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:          318423.3     0.125908     0.125619     0.126373
Scale:         319208.5     0.126040     0.125310     0.128203
Add:           320254.5     0.187974     0.187351     0.189735
Triad:         322014.6     0.186867     0.186327     0.189051
-------------------------------------------------------------
Solution Validates: avg error less than 1.000000e-13 on all three arrays
-------------------------------------------------------------

四 结果分析

Stream测试包含Copy、Scale、Add、Triad四种操作:

测试项 实际操作 访存次数/每循环 浮点计算次数/每循环
Copy a(i) = b(i) 2 0
Scale a(i) = q * b(i) 2 1
Add a(i) = b(i) + c(i) 3 1
Triad a(i) = b(i) + q * c(i) 3 2

测试结果一般的规律是Add > Triad > Copy > Scale。一次Add操作需要访问三次内存(两个读操作,一个写操作),Triad操作也需要三次访问内存,Copy和Scale操作需要两次访问内存。单位操作内,访问内存次数越多,越能够掩盖访存延迟,带宽越大。另一方面,单位操作内,浮点计算次数越多,操作完成时间越长,导致整个操作循环完成的时间越长,带宽越低。Add操作简单且访存次数多,故而带宽最大,Scale操作复杂且访存次数少,故而带宽最小。

Stream主要的调节参数如下:

  • STREAM_ARRAY_SIZE

调节测试数组的大小,可以在编译参数中通过“-DSTREAM_ARRAY_SIZE=”指定,默认为10,000,000。Stream的测试数组类型为双精度浮点,单个数组的占用内存为STREAM_ARRAY_SIZE*8字节(OFFSET为0时)。

如果数组太小,CPU Cache会干扰测试结果,不能测试出真实的内存带宽,如果数组太大,测试时间过长。Stream官方建议数组占用内存达到CPU最后一级Cache的4倍。

另外,如果STREAM_ARRAY_SIZE指定过大,单个数组超过2GB,需要在编译选项中添加“-mcmodel=medium”。

  • NTIMES

每次测试运行NTIMES,选取最好的一次输出。可以在编译参数中通过“-DNTIMES=”指定,默认为10。为增加测试结果的稳定性,可以适当增大,但测试时间也会变长。

  • OFFSET

调节数组的内存对齐。可以在编译参数中通过“-DOFFSET=”指定,默认为0,一般不用修改。

  • STREAM_TYPE

指定测试数组的数据类型,默认为double双精度浮点。可以在编译参数中通过“-DSTREAM_TYPE=float”修改为单精度。一般公认的测试均使用双精度,一般不用修改。

  • OpenMP多线程支持

gcc编译器添加“-fopenmp”选项,icc为“-qopenmp”,pgcc为“-mp”,Open64的opencc为“-openmp”。

本文系作者 @ admin 原创发布在 文档中心 | AheadAI ,未经许可,禁止转载。