ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

深度学习笔记27 深度学习硬件 CPU GPU

2022-02-18 21:34:37  阅读:177  来源: 互联网

标签:27 一个 线程 内存 深度 超线程 GPU CPU


举个例子,为什么不能用CPU做深度学习?

就拿Intel的i7来说,她每秒钟的运算是0.15TFLOPS,而NVIDIA的TitanX是12TFLOPS,两者差出80倍之多。

在实际中,你用GPU训练一个模型需要1小时的话,用CPU就需要80小时,你还玩个屁。

 

CPU:

左侧是集显区域,负责渲染图形界面,简单游戏等;中间是一些计算单元,Shared LLC是显存,其他地方都是通向其他组件的接口。

 

CPU的理论速度可能还算比较快,但是我们实际使用CPU的时候,远远达不到一个CPU的理论速度,主要原因就是主内存访问的延迟问题。

  一个式子的计算,需要从主内存,进入到CPU的显存,再从显存进入到核,最后进入到寄存器,完成运算。而主存访问延时是到寄存器访问延时的200倍。

综上,提升CPU利用率的本质就是应该提升空间和时间的内存本地性,两种方法:

  时间:重用数据使他保持在缓存中(cache提升速度)

  空间:按序读写数据使得数据可以被预读取。(CPU读取的时候,可以提前读取数据)

样例:

  如果一个矩阵是按列存储,访问一行会比访问一列要快。(这里说的是地址本身是按行还是按列,而不是数据本身的意义是按行还是按列

    CPU是按行读取,一次读取64个字节(一行,被称为缓存线),CPU会聪明地提前读取下一个(下一行,缓存线)

    故一般按行访问会快一些。

 

 提升CPU的利用率的另一个方式:加更多的核。上图是一个四核CPU,现在有些CPU的核能做到32,甚至64.

Intel提出了一个超线程,也就是更好的并行起来利用所有的核。

  网上找到一些对于超线程的理解:

常规的CPU想要执行多线程的时候,CPU要在线程之间不断地调度,在开启了超线程之后,CPU可以更充分地利用好自身的资源(CPU某些硬件有多个备份,比如程序计数器和寄存器文件)。例如当开启了超线程之后,可以在一个线程执行整数指令集的时候,而恰好在这个时候,另一个线程执行浮点指令集,而这两个指令集整数指令单元和浮点指令单元来执行。再比如一个线程必须要等到某些数据被加载到高速缓存中,那CPU就可以继续去执行另一个线程。 作者:AI草莓莓汁呀链接:https://www.zhihu.com/question/384468852/answer/1901583871

你正常情况下五秒吃一口饭,然后休息两秒,吃下一口饭,这是单线程。

你有两个嘴,一个嘴五秒吃一口饭,休息两秒,吃下一口饭;另一个嘴两秒喝一口汤,休息一秒,喝下一口汤,这是双核双线程。

你有一个嘴,五秒吃一口饭,隔壁的老王拿起你的汤碗往你嘴里灌,于是在你原本用来休息吞咽饭的两秒你又喝下了一口汤,两秒后你又开始下一个吃一口饭的五秒。这是超线程的单核双线程。

作者:路并寻链接:https://www.zhihu.com/question/384468852/answer/1122097961
但是,超线程不一定能提升性能,比如对于计算密集型的运算,但是物理意义上的寄存器就那么几个,两个超线程会抢夺寄存器,因为他们在共享寄存器。而抢夺计算资源甚至可能会降低性能。     GPU:

 

 外框是一个大核,不同品质的显卡基本就是大核不同;

大核里面有小核(绿点),每一个小核都是一个计算单元,每一个小核都能开一个计算单元,所以可以看到我们每次可以开上千个线程。

 

 

 上图的斜杠区分了两种品质,一般和高端。

可以看到,本质区别其实就是核的数目。

 除此之外,GPU的内存带宽很高,这一点非常重要,因为很大的模型再加上很多的中间数据需要经常写来写去,这可能会引起读取速度限制核的运算,所以GPU的带宽做的非常大。

另外就是CPU的控制流很强,因为CPU是通用计算单元,需要处理很多if else的东西,必须预判接下来要算的是什么,是控制流还是其他什么东西,只留下了一小部分做计算单元;与此同时,GPU把逻辑运算删掉了,基本整个芯片都在用于数据的计算。

 

提高GPU的利用率:

  1、并行,比如使用上千个线程(类似,1000维度的向量,就会产生1000个计算线程)

  2、内存本地性。GPU为了节省面积,会把缓存做的比较小,架构更简单,但同时做大了内存。

  3、tensor的运算要少用控制语句。

 

除此之外,就是CPU与GPU之间的带宽也是一个很大的问题。

有一种比喻很有意思,CPU就是几个博士生,擅长处理复杂问题;GPU就是一大堆成千上万的小学生,只会做简单的加减乘除。

CPU和内存有数据交互,同时CPU也会通过PCIE与GPU进行交互,而相对CPU与内存的带宽,CPU到GPU的带宽不是很高的,同时传输数据的时候GPU必须做好同步,这也是很大的一个开销。

所以我们不要在CPU和GPU之间传输数据,因为有带宽限制和同步开销。

 

CPU/GPU高性能编程:

  CPU:用C++或者其他高性能语言,因为这种语言的编译器很成熟。

  GPU:

    NVIDIA上用CUDA,编译器和驱动成熟。

    其他用OpenCL,质量取决于硬件厂商。

 

总结:

  

 

 

 Q&A

1、模型大小和计算复杂度没有直接关系,比如AlexNet可能300MB,ResNet18可能18MB,但是ResNet运行起来要比AlexNet慢。

2、LLC,last level of cache,就是最后一层缓存的意思。

3、尽量能够用Tensor做的,不要写for loop,不要让GPU去算逻辑性的计算。

4、python进程有一个全局锁,因为这个锁会带来很多影响,所以python常常需要多进程。

 

标签:27,一个,线程,内存,深度,超线程,GPU,CPU
来源: https://www.cnblogs.com/loveandninenine/p/15911320.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有