赞
踩
因为装3060Ti的时候踩了坑(雷?),所以不太清楚这张卡是不是如同之前想象的一样,所以这篇文章会进行一系列的实验和对比。可能对其他希望用显卡进行计算的人有所帮助。
显卡计算的特点是:只要内存不爆,那么多大的矩阵计算时间是差不多的。
如果把显卡只当成矩阵计算的工具,那么最重要的就是矩阵的尺寸/数据类型。因为矩阵占用的空间是平方增加的,所以要清除存储允许的计算上限。
float16类型在深度学习领域CNN的模型压缩,加速推理中常用,因为float32太占空间了。
这段代码来自这篇文章,我做些改造。
当前机器的配置是:
使用的计算包:
测试计算两个向量间的欧几里得距离
a = np.random.rand(1,1000000000)
b = np.random.rand(1,1000000000)
# 这段放在jupyter里面跑
%%timeit
#计算numpy计算速度
time_start=time.time()
dist1 = np.linalg.norm(a - b)#numpy求欧氏距离
time_end=time.time()
print(time_end-time_start)
可以看到,内存几乎被占满了。我们可以看到每个元素的大小(8字节)
type(a[0][0])
---
numpy.float64
速度大约是1.9s
如果有些数据的前序处理还是在内存中做,毕竟内存比较廉价。
单个向量的大小(1000000000 * 8) / 1e9 ~ 8G,在计算过程中应该是保存axb=c,所以估算总共大小约为24G。
这么大的数据如果放在显卡中计算会直接称爆显存,所以没有比较的意义。
a = np.random.rand(1,100000000)
b = np.random.rand(1,100000000)
%%timeit
#计算numpy计算速度
time_start=time.time()
dist1 = np.linalg.norm(a - b)#numpy求欧氏距离
time_end=time.time()
print(time_end-time_start)
总共需要约为192ms 。(内存估算2.4G)
c = torch.rand(1,100000000)
d = torch.rand(1,100000000)
%%timeit
#计算tensor在cpu上的计算速度
time_start=time.time()
dist2 = F.pairwise_distance(c, d, p=2)#pytorch求欧氏距离
time_end=time.time()
print(time_end-time_start)
大约花费140ms左右,比numpy还要快一点。
每个元素的大小也是64位的
从htop中观察,torch似乎调用了更多的cpu资源(内存占用反而更小一些)
e = torch.rand(1,100000000).cuda()
f = torch.rand(1,100000000).cuda()
%%timeit
#计算tensor在cuda上的计算速度
time_start=time.time()
# 我计算结果的精度调高,原例子是p=2
dist2 = F.pairwise_distance(e, f, p=5)
time_end=time.time()
print(time_end-time_start)
结果不到6ms的时间。
显卡状态,可以看到这个计算几乎让显卡满载
和CPU比较,使用显卡计算的速度倍数提升约为23.5倍(141/6)。这个例子似乎CPU并没有完全满载(半载),可以认为GPU比CPU快10倍,之后可以在别的场景再比较。
显卡价格: ¥2,999 (差不多是30系性价比之王了吧)
CPU价格: ¥999
价格上显卡是CPU的3倍,算力是CPU的10倍,能耗是CPU的3倍,从计算角度上还是比较划算的,不过也并没有想象的差距那么大。以后有机会和同价格的CPUpk一下(3900x,理论上速度应该是3400G的3.3倍):
cpu的算力估计可以参考这篇文章
简单点估算
CPU的算力与CPU的核心的个数,核心的频率,核心单时钟周期的能力三个因素有关系
常用双精度浮点运算能力衡量CPU的科学计算的能力,就是处理64bit小数点浮动数据的能力
支持AVX2的处理器在1个核心1个时钟周期可以执行16次浮点运算,也称为16FLOPs
CPU的算力=核心的个数 x 核心的频率 x 16FLOPs
支持AVX512的处理器在1个核心1个时钟周期可以执行32次浮点运算,也称为32FLOPs
CPU的算力=核心的个数 x 核心的频率 x 32FLOPs
CPU的算力=核心的个数 x 核心的频率 x 32 FLOPs = 8 * 3.7g X32 = 0.95TFLOPS
如果按这个来估计,那么3060Ti应该是10T左右的算力,但10倍是基于之前htop看到的cpu资源耗费比计算的(有可能cpu本身的浮点计算已经全部用满了);假设cpu已经全力计算,那么3060Ti的浮点算力接近20T,和之前估计的就比较接近。
还有就是单精度,或者双精度的影响,参考
那么按这个来算, 3060ti的算力(未超频版,取主频中值估计):
(4864/2)*1.5 G* 2 = 7.3T
4864*1.5 * 2 = 14.5T
默认情况下测试似乎是按fp32跑了,我将类型改为fp16, 果然又快了一倍。
import torch from torch.functional import F e = torch.rand(1,100000000).cuda() f = torch.rand(1,100000000).cuda() %%timeit #计算tensor在cuda上的计算速度 time_start=time.time() # 我计算结果的精度调高,原例子是p=2 dist2 = F.pairwise_distance(e, f, p=5) time_end=time.time() print(time_end-time_start) --- ... 0.020745515823364258 0.020746707916259766 0.02073812484741211 20.7 ms ± 21.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
1060显卡的执行过程监督
从时间的倍数上看,3060Ti的计算性能是1060的3.55倍;价格的化3060Ti是¥2999,1060价格是¥1100左右,2.72倍。当然除了计算性能之外,3060Ti的显存更大,速度更快(8G GDDR6 vs 5G GDDR5)。另外,CUDA单元方面3060Ti是4680个CUDA单元,而1060是1280个CUDA单元,3060Ti是3.65倍;核心频率方面 ,3060Ti的GPU基础频率1410MHz,加速频率1665MHz;1060的核心频率1506MHz,Boost频率1709MHz,总体上差不多吧。
import time import numpy as np a = np.random.rand(1,100000000) b = np.random.rand(1,100000000) %%timeit #计算numpy计算速度 time_start=time.time() dist1 = np.linalg.norm(a - b)#numpy求欧氏距离 time_end=time.time() print(time_end-time_start) --- ... 0.2752072811126709 0.27521586418151855 0.2744309902191162 275 ms ± 805 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
使用pytorch cpu版计算会比numpy稍微快几毫秒。
import numpy as np a = np.random.rand(1,100000000) b = np.random.rand(1,100000000) %%timeit #计算numpy计算速度 time_start=time.time() dist1 = np.linalg.norm(a - b)#numpy求欧氏距离 time_end=time.time() print(time_end-time_start) --- 0.22238779067993164 0.2396526336669922 0.2394123077392578 0.23943424224853516 0.23966670036315918 0.2403874397277832 0.2395646572113037 0.23941373825073242 240 ms ± 323 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
在使用pytorch cpu计算时,速度反而慢了一大截。可能和cpu、cuda版本这些都有关系
import torch from torch.functional import F e = torch.rand(1,100000000).cuda() f = torch.rand(1,100000000).cuda() %%timeit #计算tensor在cuda上的计算速度 time_start=time.time() # 我计算结果的精度调高,原例子是p=2 dist2 = F.pairwise_distance(e, f, p=5) time_end=time.time() print(time_end-time_start) --- ... 0.39830899238586426 0.4005136489868164 0.39644789695739746 397 ms ± 1.64 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
我买的是i7的cpu,4核8G,整体性能(1.7S)和3400G相仿(1.9S)。在能耗上肯定是i7胜出,并且还带了集显。
import numpy as np
a = np.random.rand(1,1000000000)
b = np.random.rand(1,1000000000)
%%timeit
dist1 = np.linalg.norm(a - b)
1.7 s ± 1.41 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
订购了一个M1 Pro的满血版,还没有拿到。看到有些文章给了几款CPU的算力(估计是单精度浮点的),记录一下:
型号 | 算力 | 备注 |
---|---|---|
M1 | 2.7T | 从M1 Pro 16GPU推断 |
M1 Pro 16GPU | 5.2T | 2048个EU,30w功率,接近3050Ti |
M1 Max | 10.4 T |
回头拿到机器在计算对比一下。
使用conda方式安装了jupyter之后,运行一亿欧几里得测试
import pandas as pd import numpy as np import time a = np.random.rand(1,100000000) b = np.random.rand(1,100000000) %%timeit #计算numpy计算速度 time_start=time.time() dist1 = np.linalg.norm(a - b)#numpy求欧氏距离 time_end=time.time() print(time_end-time_start) --- 142 ms ± 1.07 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
这个算力看起来类似3400G的算力,倒是比较符合我的预期。不过目前的方法似乎不太能够调出m1 pro的所有算力,看起来只是一个cpu核在计算(甚至gpu都不知道如何调用)。
看来如何调用出m1 pro的算力是个问题。
这个待续 >>>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。