体系结构实验(1)—— 计算机性能评测

Chapter 1 LAB Computer Performance Evaluation

P1:Bechmark software evaluation

要求:Choose one benchmark software to evaluate your computer, give the evaluation report, list the first three parameters you learned in the Lab, describe possible errors that may have happened in the course of the experiment and your solutions to them.

1.1 处理器性能报表

在这里插入图片描述

参数名参数值含义
名字AMD Ryzen 7 5800H处理器的名字
代号Cezanne核心代号,用于区分处理的核心架构
TDB45.0W热设计功耗:同一系列处理器,TDP越大,性能越强。TDP是一个可以修改的参数,并不是实际功耗。TDP设定的越高,处理器就越不容易降频,即不容易出现性能下降。
插槽Socket FP6封装形式
工艺7纳米制造工艺纳米数越小,代表越精细,处理器也就越先进。
核心电压1.350V同一架构处理器的核心电压在同一主频率的对比中,电压越低代表处理器的体质越好
规格AMD Ryzen 7 5800H with Radeon Graphics完整的处理器型号以及设定的标准主频
系列/拓展系列F/19AMD处理器的系列都是F,扩展系列是19
型号/拓展型号0/50这组数据其实是处理器架构的决定数据
步进/修订0/CZA-A0同一型号的正式版处理器如果修订号存在差别,那么其实际功能也会存在差异
指令集MMX(+),SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2, SSE4A,x86-64,AMD-V,AES,AvX,AVX2,FMA3,SHA拓展指令集he
核心速度2934.05HZ当前处理器核心的速度倍数
倍频*29.4处理器节能技术实现的关键就是倍频一直在变
总线速度99.80MHz主频
FSB已淘汰处理器节能技术实现的关键就是倍频一直在变
一级数据/数据8*32KBytes处理器每一个核心都是同时具备一级指令缓存以及一级数据缓存的。该处理器有8个核心
二级缓存8*512KBytes每个核心分配512KB二级缓存,一共有8个核心
三级缓存16MBytes三级缓存是所有核心共享的
核心数8物理核心的数目为8,这里表示8核处理器
线程数16支持超线程技术的处理器,线程数是核心数的两倍

拓展指令集相关解读

【MMX】

MMX是X86处理器首个加入的扩展指令集,于1997年首次出现在奔腾MMX处理器中,是处理器中最重要的提升多媒体性能的扩展指令集,AMD的MMX(+)是对MMX指令集进一步完善之后的结果(AMD原先还有个3D NOW!指令集);

【SSE家族】

SSE指令集家族本质上是MMX的延伸,主要还是提升了处理器的多媒体能力以及运算性能。其中SSSE3指令集是英特尔酷睿架构的标志,当然,它后来也被应用在AMD处理器中。AMD的SSE4A可以理解为是对SSE4系列指令集的补充;

EM64T(英特尔)/X86-64(AMD)】具备这两种扩展指令集的处理器就是我们所说的64位处理器,可以安装64位操作系统。AMD早在2003年就已经将64位扩展指令集应用在自家消费级处理器上,英特尔则是晚了好久;

VT-X(英特尔)/AMD-V(AMD)】虚拟化技术,最早是由AMD向广大用户普及的,英特尔之前只有高端处理器才有这一指令集;

AES】加密运算指令集;

AVX/AVX2】浮点运算扩展指令集,这一指令集极大地提升了处理器的浮点运算能力;

FMA3/FMA4(AMD)FMA指令集(英语:Fused-Multiply-Add,即积和熔加运算)是x86架构微处理器上的指令集。FMA指令集是128位和256比特的流式单指令流多资料流扩展集(SSE)指令集,以进行积和熔加运算。FMA4:是一种四元运算指令集。FMA3:是一种三元运算指令集

TSX】TSX命途多舛,一度在Haswell以及Broadwell处理器上被禁用,因为存在运算BUG,TSX的设计初衷是为了提升处理器多线程运算的效率。

主频,总线速度和倍频的关系

倍频X总线速度=主频。处理器节能技术实现的关键就是倍频一直在变。

1.2 主板性能报表

在这里插入图片描述

参数名参数值含义
制造商LENOVO联想公司
模型LNVNB161216 SDKOL77769 WIN主板模型
通道规格PCI-Express 4.0(16.0 GT/s)采用PCI总线,传输速度是16.0GT/s
芯片组AMD Ryzen soc采用的芯片组
南桥Carrizo FCH南桥的型号
BIOSLENOVO/ HHCH14WWBIOS版本号
版本PCI-Express 4.0图形接口版本
当前连接频x8当前连接频
连接频最大支持x16最大可以支持的连接频
当前连接速度2.5 GT/s当前测试时的连接速度
连接速度最大支持16.0GT/s理论最大连接速度

1.3 内存性能报表

在这里插入图片描述

参数名参数值含义
类型DDR4内存的类型
通道数2*64-bit内存的通道数
大小16GBytes内存的大小
北桥频率1596.8 MHz内存的南桥频率
内存频率1596.8MHz内存的频率
FSB:DRAM1:16FSB和DRAM的比值
CL22.0时钟CAS Latency
tRCD22时钟RAS to CAS Delay
tRP22时钟Row PreCharge Time
rRAS52时钟Row Active Time
tCR74时钟Command Rate

tCR详解:tCR也称为指令比率和指令周期。通常有一个特定的-T后缀,在超频时经常可以看到,它表示命令速率。AMD将命令速率定义为从选定DRAM芯片到执行命令之间的时间,以周期为单位。它可以是1T或2T,其中2T CR对于更高的内存时钟或4-DIMM配置的稳定性非常有利。CR有时也称为命令周期。虽然1T更快,但在某些场景中2T可能更稳定。它也像其他内存计时一样以时钟周期来衡量,尽管它使用唯一的-T符号。两者在性能上的差异可以忽略不计。

P2: Analyze linkpack.c program

要求:Run the given linpack.c program on your computer, analyze the results and analyze this benchmark program which you might have to do some modifications. Give the evaluation results and submit your revised version.

2. 1 算法流程

2.1.1 关键代码片分析

Linpack100通过求解规模为100阶的稠密线性代数方程组来衡量

//line 27
// SP 代表是单精度,类型为float
#ifdef SP
#define REAL float
#define ZERO 0.0
#define ONE 1.0
#define PREC "Single "
#endif
// line 39
// DP 是双精度,类型为double
#ifdef DP
#define REAL double
#define ZERO 0.0e0
#define ONE 1.0e0
#define PREC "Double "
#endif
// line 157
// 计算规模为n, for循环n次。每次循环过程(对向量矩阵进行一次原子操作)完成一次加法和一次乘法。
#ifdef ROLL
    for (i = 0;i < n; i++) {
        //printf("2.1.1.2.1: dy[%d]=%f\n", i, dy[i]);
        dy[i] = dy[i] + da*dx[i];
        //printf("2.1.1.2.2: dy[%d]=%f\n", i, dy[i]);
    }
#endif
// line 164
// UNROLL 表示进行n/4次循环,每次循环完成四次加法和四次乘法。
#ifdef UNROLL

    m = n % 4;
    if ( m != 0) {
        for (i = 0; i < m; i++) {
            dy[i] = dy[i] + da*dx[i];
            //printf("2.1.1.3: dy[%d]=%f\n", i, dy[i]);
        }
        if (n < 4) return;
    }
    for (i = m; i < n; i = i + 4) {
        dy[i] = dy[i] + da*dx[i];
        //printf("2.1.1.4: dy[%d]=%f\n", i, dy[i]);
        dy[i+1] = dy[i+1] + da*dx[i+1];
        //printf("2.1.1.4: dy[%d]=%f\n", i+1, dy[i+1]);
        dy[i+2] = dy[i+2] + da*dx[i+2];
        //printf("2.1.1.4: dy[%d]=%f\n", i+2, dy[i+2]);
        dy[i+3] = dy[i+3] + da*dx[i+3];
        //printf("2.1.1.4: dy[%d]=%f\n", i+3, dy[i+3]);
    }
#endif
}
// line 67
// atime 数组定义了测试代码执行的相关结果
static REAL atime[9][9];
// line 770 
// 计算规模为n时,计算的次数为 2/3*n^3+2*n^2
// 其中dgefa计算此时为2/3*n^3,dgesl的计算次数为2*n^2。 因此大部分的时间花在dgefa的计算上。
ops = (2.0e0*(n*n*n))/3.0 + 2.0*(n*n);
// line 753
// 使用的矩阵规模有两种,分别是200*201与200*200。
//采用两种不同规模矩阵的原因:
// linpack 在计算的过程中需要从矩阵中取数,计算机中设有数据缓冲区,大规模的计算效率对于命中率有很高的要求。因此设置不同规模大小的矩阵(在内存中的映射不同,命中率也会不同),取其中性能最优者作为评测的结果。
static REAL aa[200][200],a[200][201]
// line 84
// 声明matgen函数,该函数会随机生成一个a*lda大小的矩阵
void matgen(a,lda,n,b,norma)
// line 554 
// 声明dmxpy函数,该函数用矩阵m乘以向量x,并将结果加到y上。即 m*x+y
void dmxpy (n1, y, n2, ldm, x, m)
// line 638 
// 声明了dgefa函数, 采用高斯消去法对双精度矩阵进行因子分解。
// 其中 a 表示待计算的矩阵,大小为n*lda ; 
// a可以分解为 a=l*u, 其中l是置换矩阵和单位下三角矩阵的乘积,u 是上三角矩阵。
// ipvt[n] 表示的是主指标(pivot indices)的向量
void dgefa(a,lda,n,ipvt,info)
// line 188
// 定义了dgesl函数,用来计算dgefa因子分解后的双精度算式,例如 a*x=b 或者 a'*x=b (a'是a的转置)
// 其中a表示的是dgefa分解后得到的矩阵,大小为n*lda
// ipvt 表示的是dgefa分解后得到的主向量(pivot vector)
// b表示的是等式最右边的结果向量
// job 是一个标志位,当其值为0的时候,计算 a*x=b ; 其结果不为0的时候,计算 a'*x=b (a'是a的转置)
void dgesl(a,lda,n,ipvt,b,job)
// line 780 
// atime[0][0] 保存的是 dgefa 函数计算的时间
    t1 = second();
    dgefa(a,lda,n,ipvt,&info);
    atime[0][0] = second() - t1;
// line 784 
// atime[1][0] 保存的是 dgesl 函数计算的时间
    t1 = second();
    dgesl(a,lda,n,ipvt,b,0);
    atime[1][0] = second() - t1;
// line 788 
// total总时间 = dgefa计算时间 + dgesl 计算时间
    total = atime[0][0] + atime[1][0];
// line 853
// atime[2][0]  保存 dgefa+dgesl 的计算总时间total
// atime[3][0]  保存 ops/(total*10^3) 的中间结果,及kflops的值(每秒进行多少千次的浮点运算)
// atime[4][0]  保存 2*total*10^3/ops*10^3 的值
// atime[5][0]  保存 total/cray 的值,其中cray =0.056
    atime[2][0] = total;
    atime[3][0] = ops/(1.0e3*total);
    atime[4][0] = 2.0e3/atime[3][0];
    atime[5][0] = total/cray;
// line 963
// kf 选取 atime[3][3] 和 atime[3][7] 中的较小者, 即在aa[200][200],a[200][201]的计算结果中选取ops/(total*10^3) 最小值,即total值较大的(耗时更长的矩阵)
// 如果 kf>0 则 kf=kf+0.5 ; 如果kf<0, 则kf=kf-0.5
// 如果 kf < 1 则 kflops = 0 ; (这一步和上一步等价为: 如果kf四舍五入后的绝对值仍然小于1,则 kflops = 0)
// 否则 kflops = |floor(fabs((double)kf))|
	kf = (atime[3][3] < atime[3][7]) ? atime[3][3] : atime[3][7];
    kf = (kf > ZERO) ? (kf + .5) : (kf - .5);
    if (fabs((double)kf) < ONE)
        kflops = 0;
    else {
        kflops = floor(fabs((double)kf));
        if (kf < ZERO) kflops = -kflops;
    }
2.1.2 算法流程架构

整体算法流程图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kRNVzdyO-1664955925556)(C:\Users\zpy\Pictures\绘图1.png)]

2.2 分析和结论

2.2.1 中间过程分析
  • 1: b[i]=0.000000是第772行的代码打印的结果,表示为对b初始化之前的向量b[]的值都为0。

在这里插入图片描述

  • 2:b[i]=xx.xxxxxx 是第776行代码打印的结果,表示经过matgen函数随机初始化后,b[i]的值为随机数。

在这里插入图片描述

  • 3:b[i]=1.000000 是第791行代码打印的结果,表示经过dgefa()和dgesl()两个函数分别处理后,b[i]的值均为1。

在这里插入图片描述

  • x[i]=0.000000 b[0]=1.000000 是第797行代码运算的结果,表示经过dgefa()和dgesl()两个函数分别处理后,b[i]的值均为1,x[i]的值均为0。

在这里插入图片描述

  • residn resid eps x[0]-1 x[n-1]-1

    第一列表示residn(norm.resid),用来衡量计算的精度,其结果都为0,表示精度较高,残差很小。

    第二列表示resid,表示未归一化的值

    第三列表示eps(mechep),用于度量计算的精度。在IEEE浮点计算机上,这个值应该是2.22044605e-16。

    第四列和第5列分别表示x[0]-1和x[n-1]的值,是解的第一个和最后一个分量, 问题的构造使得其结果都趋近于0。

在这里插入图片描述

最后一行根据公式residn = resid/( n*norma*normx*eps ); 重新计算residn的值。

在这里插入图片描述

2.2.2 测量结果分析
  • n =100 ntimes=10

    • ROLLED SINGLE
      在这里插入图片描述

    • ROLLED DOUBLE
      在这里插入图片描述

    • UNROLLED DOUBLE

在这里插入图片描述

  • UNROLLED SINGLE
    在这里插入图片描述
ROLLING/PRECSPDP
ROLLED980953 kflops980952 kflops
UNROLLED1373335 kflops1373333 kflops

综合上述结果可以看出,dgefa 和 degesl 的计算时间都很小,保留两位小数后都趋近于0。total= dgefa + dgesl 因此total的时间也趋近于0。然后最终的kflops选取的是第四列第四行和第八行中较小的值,印证了代码中选取 a [ 3 ] [ 7 ] a[3][7] a[3][7] a [ 7 ] [ 7 ] a[7][7] a[7][7]中的较小者作为Kflops( 每秒进行多少千次的浮点计算) 。

上图结果可以看出单精度浮点运算比双精度浮点运算略快1~2kflops,但整体差别不大。因为单精度就是指32bit的指令长度的运算,对应操作系统就是32位操作系统;双精度就是指64bit指令长度的运算,对应操作系统就是64位操作系统。我的电脑是64位的操作系统,所以只有DP的计算比较有意义。

除此之外,在n和ntimes相同的情况下:当采用ROLL方法进行计算比采用UNROLLED方法计算得到的flops值要小。因为在采用UNROLLED的方法计算时,每个 循环可以计算dy[i],dy[i+1],dy[i+2],dy[i+3] 它们在内存中的位置紧挨在一起,在内存中查找相关数据的执行效率更高。因此用UNROLLED的方法flops值更高。

其中根据第一问的CPU-Z的性能报告可以看出:我的电脑支持的高级矢量指令集是AVX2, 其中AVX2的处理器的单指令的长度是256bit,每颗CPU包含4个FMA,一个FMA一个时钟周期可以进行2次乘或者加的运算,那么这个处理器在1个核心1个时钟周期可以执行 256 b i t ∗ 4 ∗ 2 / 64 = 32 256bit*4*2/64=32 256bit42/64=32次双浮点运算,执行 256 b i t ∗ 4 ∗ 2 / 32 = 64 256bit*4*2/32=64 256bit42/32=64次单精度浮点计算。

在这里插入图片描述

AMD Ryzen 7 5800H CPU是8核,根据联想电脑管家在运行linpack时测出的的数据,每个核的基准时钟周期频率为4.1 GHZ。

理论单精度的浮点计算的峰值 = 8 ∗ 4.1 ∗ ( 2 ∗ 4 ∗ 256 / 32 ) = 1049.6 G f l o p s 理论单精度的浮点计算的峰值=8*4.1*(2*4*256/32)=1049.6Gflops 理论单精度的浮点计算的峰值=84.1(24256/32)=1049.6Gflops

理论双精度的浮点计算的峰值 = 8 ∗ 4.1 ∗ ( 2 ∗ 4 ∗ 256 / 64 ) = 2099.2 G f l o p s 理论双精度的浮点计算的峰值=8*4.1*(2*4*256/64)=2099.2Gflops 理论双精度的浮点计算的峰值=84.1(24256/64)=2099.2Gflops

用linpack实测的双精度浮点计算的峰值要小于理论的峰值。除此之外,由于同一台计算机负载情况的不同,从而导致测试结果在同一台机器上的测试结果也可能不同。

除此之外,通过控制其他的值不变(n=100),改变ntimes的值, 测量双精度浮点运算的kflops的值。随着ntimes的改变,单位时间内双精度浮点运算的次数没有太大的变化。如下表所示:

在这里插入图片描述

通过控制其他的值不变(ntimes=100),改变n的值, 测量双精度浮点运算的kflops的值。随着n的增加,单位时间内双精度浮点运算的次数呈上升趋势。且Unrolled的模式下,上升的趋势更快。如下表所示:

3. 参考

[Frequent Asked Questions on the LINPACK Benchmark (netlib.org)](http://www.netlib.org/utk/people/JackDongarra/faq-linpack.html#_What_is_the_theoretical peak perfor)

AMD Ryzen™ 7 5800H | AMD

linpack Benchmark_文档之家 (doczj.com)

关于CPU的浮点运算能力计算 - 简书 (jianshu.com)

处理器和GPU的计算能力如何计算? - 知乎 (zhihu.com)

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zyw2002

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值