深入理解计算机基础第五章
前言
性能分析软件 vtune
关于如何精确测量花费时间 + 最小二乘法python脚本
uint64_t current_cycles(){
uint32_t low, high;
asm volatile("rdtsc" : "=a"(low), "=d"(high));
return static_cast<uint64_t>(low) | (static_cast<uint64_t>(high) << 32);
}
默认从InputData.txt读取数据,每行一个坐标\((x_i,y_i)\),不要有行末空格
1 5
2 -3
-5 5
linux上bash python LeastSquareMethod.py InputData.txt
安装依赖库
sudo apt-get install python-numpy
sudo apt-get install python-scipy
sudo apt-get install python-matplotlib
#!/usr/bin/python
# -*- coding: UTF-8 -*-
############################################
# Copyright XDU'QingHuan #
# LeastSquareMethod.py #
# Input : InputData.txt #
# Output : ResultPicture.png | y = kx + b #
############################################
import sys
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
from scipy.optimize import leastsq
### Get input file name
InputFileName = "InputData.txt"
if len(sys.argv) == 2:
InputFileName = sys.argv[1]
### Get input data from InputData.txt
Xi = np.array([])
Yi = np.array([])
for line in open(InputFileName, "r").read().split("\n"):
[a,b] = line.split(" ");
Xi = np.append(Xi,float(a));
Yi = np.append(Yi,float(b));
### Required parameters
def func(p,x):
k,b = p
return k * x + b
def error(p,x,y):
return func(p,x) - y
### Calculate least squares
k,b = leastsq(error,[0,0],args=(Xi,Yi))[0]
### Generate results
print("y = " + str(round(k,3)) + "x + "+str(round(b,3)))
plt.scatter(Xi,Yi,color="green",label="Input data",linewidth = 2)
x = np.linspace(np.max(Xi),np.min(Xi),2)
y = k * x + b
plt.plot(x,y,color = "red",label = "Fitting curve",linewidth = 2)
plt.legend(loc = 'lower right') #绘制图例
plt.savefig('ResultPicture.png')
一些关于常识
int--> short/char (0~1 clock cycle)
int --> float/double (4~16个clock cycle), signed int 快于 unsigned int,唯一一个场景 signed 比 unsigned 快的
short/char 的计算通常使用 32bit 存储,只是返回的时候做了截取,故只在要考虑内存大小的时候才使用short/char,如 array
注:隐式类型转换可能会溢出,有符号的溢出变成负数,无符号的溢出变成小的整数
除法、取余运算unsigned int 快于 signed int,此外除以常量和除以变量可能有几倍的性能差距
单精度和双精度的浮点计算性能一样感觉这条不太对
不要混淆单双精度,精度转换会带来额外的性能开销
关于如何测量CPE
upd : 测量结果完全不具备参考性...水平不足难以分析原因...并且各种高级优化跑不过直接开O1优化...
CPE : 每元素的周期数
也就是处理每个元素花费多少指令周期
比如我的电脑是2.20GHz,也就是 \(\frac{1}{2.20 * 10^9} = 0.4545 * 10^{-9}s\) 执行一条指令
然后的难点就是测量函数运行的时间,因为要考虑避开cache等的影响,需要测量小数据...
这样导致对测量精度要求非常高,折中的办法是测量 1000000 次这样
各种测量时间的姿势 : https://blog.csdn.net/jhcconan614/article/details/56495600/
python-最小二乘脚本 : https://www.cnblogs.com/dahu-daqing/p/9514457.html
自己用python写个文件读入什么的就行了
经过实验,clock函数好一点,毫秒级,结果比较稳定
这是跑\(10^6\)次,2.2Ghz G7下,得到的结果,脚本会计算拟合曲线
y = kx + b,b的误差比较大,但是k是比较稳定的,测量\(10^5\)次都不太稳定,但是测量\(10^6\)次就很稳定了
相应的...我测量一次需要120s...
关于书上测量CPE的例子
我加了各种优化,没有开O1优化跑的快...并且结果完全没有参考性
可能是因为个人笔记本的影响因素比较多,所以完全测量不出什么有意义的结果
关于优化的一些基本知识
错误的优化不如不优化
这个定理比较重要 (计组老师 : 都大学生了起码要会量化你的结果)
1.优先处理复杂度高的情况
2.注意浮点运算的性质、函数的副作用、指针别名导致的,编译器不做冒险的优化
3.各种优化手段目的是提高并行性,最大化利用CPU的计算运算单元
4.超标量 :同一个时钟周期内可以执行多个指令
5.超流水 :一般把流水线阶段比较深的都称为超流水
6.超标量超流水 :上两个结合起来
7.减少过程调用可能会损坏模块性
8.边界check不一定导致性能下降 :因为分支预测
对单元功能的刻画
1.延迟 :完成运算需要的总时间
2.发射 :两个连续的同类型的运算之间需要的最小时钟周期 (发射为 1 的被称为完全流水线化)
3.容量 :能执行该操作的单元的数量
4.吞吐量 : 吞吐量 : \(\frac{容量}{发射时间}\)
吞吐量界限是处理器单元的原始计算能力,这是性能的终极界限
当指令必须按照一定的时序发生时,延迟界限就会制约性能
还有一些别的东西会限制性能
循环展开
这种技术可以减短关键路径的长度,从而提高并行性
对于延迟为L,容量为C的运算而言,当循环展开因子\(k \geq L * C\)时,才能达到吞吐量界限
循环展开因子太大,会导致寄存器溢出,从而降低性能
重新结合变换
这东西比较鬼畜,简单来说就是可以通过变换结合方式(通过() 改变运算顺序)
得到\(k \times 1\)的循环展开效果
分支预测
不必太过关心这东西,现代处理器能很好的识别各种预测模式
值得注意的是,条件传送指令可以被实现为普通指令流水线化处理的一部分,不会导致错误惩罚
加载的性能
尽力避开cache抖动,这非常消耗性能
其他的先咕咕咕
本文来自博客园,作者:XDU18清欢,转载请注明原文链接:https://www.cnblogs.com/XDU-mzb/p/14961401.html