CPU和GPU的运算机制的差异

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CPU和GPU的运算机制的差异相关的知识,希望对你有一定的参考价值。

简单通俗点好,挑要点解释就好

GPU在几个主要方面有别于DSP架构。其所有计算均使用浮点算法,而且目前还没有位或整数运算指令。此外,由于GPU专为图像处理设计,因此存储系统实际上是一个二维的分段存储空间,包括一个区段号(从中读取图像)和二维地址(图像中的X、Y坐标)。此外,没有任何间接写指令。输出写地址由光栅处理器确定,而且不能由程序改变。这对于自然分布在存储器之中的算法而言是极大的挑战。最后一点,不同碎片的处理过程间不允许通信。实际上,碎片处理器是一个SIMD数据并行执行单元,在所有碎片中独立执行代码。
尽管有上述约束,但是GPU还是可以有效地执行多种运算,从线性代数和信号处理到数值仿真。虽然概念简单,但新用户在使用GPU计算时还是会感到迷惑,因为GPU需要专有的图形知识。这种情况下,一些软件工具可以提供帮助。两种高级描影语言CG和HLSL能够让用户编写类似C的代码,随后编译成碎片程序汇编语言。Brook是专为GPU计算设计,且不需要图形知识的高级语言。因此对第一次使用GPU进行开发的工作人员而言,它可以算是一个很好的起点。Brook是C语言的延伸,整合了可以直接映射到GPU的简单数据并行编程构造。经 GPU存储和操作的数据被形象地比喻成“流”(stream),类似于标准C中的数组。核心(Kernel)是在流上操作的函数。在一系列输入流上调用一个核心函数意味着在流元素上实施了隐含的循环,即对每一个流元素调用核心体。Brook还提供了约简机制,例如对一个流中所有的元素进行和、最大值或乘积计算。Brook还完全隐藏了图形API的所有细节,并把GPU中类似二维存储器系统这样许多用户不熟悉的部分进行了虚拟化处理。用Brook编写的应用程序包括线性代数子程序、快速傅立叶转换、光线追踪和图像处理。利用ATI的X800XT和Nvidia的GeForce 6800 Ultra型GPU,在相同高速缓存、SSE汇编优化Pentium 4执行条件下,许多此类应用的速度提升高达7倍之多。
对GPU计算感兴趣的用户努力将算法映射到图形基本元素。类似Brook这样的高级编程语言的问世使编程新手也能够很容易就掌握GPU的性能优势。访问GPU计算功能的便利性也使得GPU的演变将继续下去,不仅仅作为绘制引擎,而是会成为个人电脑的主要计算引擎。
简单点说:GPU是图形处理器,CPU是中央处理器.CPU是单线处理指令.而GPU是并行处理.
参考技术A 就一般通用处理器来说,在浮点运算、并行处理方面性能远不如GPU。我们可以将GPU的优势发挥出来,使处理器性能得到大幅提高。从更深层次考虑,目前CPU的性能提升遇到了各种各样的困难,除了难以攀升的核心频率之外,核心架构效率、核心数量都很难获得大幅提升。反观GPU就是一番不同的景象了,它的潜力还未被完全的挖掘,提升空间巨大。
首先:处理器核心频率遭遇瓶颈!
细心的消费者会发现近年来处理器已经不再使用核心频率来作为处理器的型号标注。其中一个非常重要的原因就是处理器主频在现有工艺条件之下已经遭遇瓶颈难以继续攀升,想要再依靠频率大幅度提升处理器性能已经走不通了。

然后:处理器核心效率挖掘殆尽!

既然频率已经不能够再提升了,我们可否提升处理器的运行效率来提高处理性能呢?这在一方面是完全可行的,但是提升幅度也非常有限。

目前Intel最强的酷睿 i7处理器,架构方面相比上代酷睿2四核处理器发生了巨大的改变:原生四核、三级缓存、高速QPI总线、三通道DDR3内存控制器、超线程技术、内核及指令集优化等等。在这些技术共同优化之下同频率酷睿i7 965综合性能仅比上代QX9770提升了10-20%,架构的潜力已经被深度挖掘几乎殆尽。

AMD情况也相差不错,Phenom II相比Phenom的性能提升更多源于频率,而核心架构优化贡献仅有不到5%。两大处理器厂商单核心效率都已接近极限,想要继续提升举步维艰。

最后:CPU核心数量增加已达上限!

频率难以提升,核心效率挖掘殆尽,那我们就多加几个核心一起来提高性能好了,不过这也不是简单的事情。从最初的胶水双核到后来的原生四核,再到现在的顶级六核,核心增加变得越来越困难,这其中必定是有原因的。

GPU拥有超高的浮点运算能力!

GPU的运算能力与日俱增,现阶段还是针对图像运算居多,主要还是进行浮点运算和并行处理。通用处理器则更多的是针对整数运算,所以说GPU与通用处理器(General Purpose Processor)设计领域侧重各有不同。
CPU仍然有存在价值,由于通用处理器的设计,令它可以应付日常生活形形色色的工作,所以它与GPU的关系应该是并存的。如CPU负责一般整数运算,而GPU则负责专门浮点计算。如果能够把这两者完美的整合起来,并由此延伸出可供实际运用的架构,必将带来处理器发展的新纪元。

照这样看来CPU与GPU整合确实是一个非常NB的点子啊!那我们要怎么才能做到呢?请点此让我为大家介绍下现在的实际运用例子。

具体参考:http://tech.sina.com.cn/h/2010-08-19/06051464143.shtml

参考资料:http://tech.sina.com.cn/h/2010-08-19/06051464143.shtml

参考技术B CPU的任务包括了T&L(多边形转换与光源处理,也就是3D显示运算),浮点运算、还要做内存管理、输入响应等非3D图形处理工作,而GPU是专门做T&L运算的,同时也具备一定的浮点运算能力。也就是说,CPU什么都能算但是不够专精,GPU专门做图形处理运算,用来显示2D、3D图像。 参考技术C 我说点自己的理解吧

CPU是一个通用处理器,也就是什么都能干,但是不精
GPU是专用处理器,专搞图形的,当然这方面就比较猛

后来有人发现GPU也可以干图形之外的事,而且因为架构的原因,性能比CPU还好,所以就发展了GPU的通用计算

CPU什么都能干,付出的代价就是,它的晶体管中,多数是用来控制的,少数用来运算,当然速度就慢;而GPU中多数晶体管是用来运算的,速度就快。

好像还有个区别,就是GPU在设计的初期,为了绘图上的需求,做成了多个流处理器的,大概和CPU的多核差不多吧,也就是并行处理能力很强。
参考技术D 嗯,这个问题大!
cpu是管控制的、运算,所有运算!
GPU是对图像的运算,因为现在图像的运算很费时间,所以给CPU一个助理来帮助它,这就是GPU!
这就是差异,在越来越强调图形图像的今天,GPU显得格外重要!

Javascript如何实现GPU加速?

一、什么是Javascript实现GPU加速?

CPU与GPU设计目标不同,导致它们之间内部结构差异很大。
CPU需要应对通用场景,内部结构非常复杂。
而GPU往往面向数据类型统一,且相互无依赖的计算。
所以,我们在Web上实现3D场景时,通常使用WebGL利用GPU运算(大量顶点)。
但是,如果只是通用的计算场景呢?比如处理图片中大量像素信息,我们有办法使用GPU资源吗?这正是本文要讲的,GPU通用计算,简称GPGPU。

二、实例演示:色块识别。

如下图所示,我们识别图片中彩虹糖色块,给糖果添加表情。

 

2.1、实例地址(打开页面后,依次点击按钮“使用CPU计算”、“使用GPU计算”):
http://tgideas.qq.com/2018/brucewan/gpgpu.html

2.2、运行代码:

 1 var rgb2hsv = function(r, g, b) {
 2     var max = Math.max(r, g, b), min = Math.min(r, g, b),
 3         d = max - min,
 4         h,
 5         s = (max === 0 ? 0 : d / max),
 6         v = max / 255;
 7     switch (max) {
 8         case min: h = 0; break;
 9         case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break;
10         case g: h = (b - r) + d * 2; h /= 6 * d; break;
11         case b: h = (r - g) + d * 4; h /= 6 * d; break;
12     }
13     return {
14         h: self.hueIndexs[parseInt(h*360)],
15         s: s,
16         v: v
17     }
18 };

  运行次数:262144次

2.3、测试结论:
实例中,我们分别使用GPU和CPU进行色相转换(防止光线影响识别准确度),其余步骤均一致。

测试平台 测试结论
PC GPU较CPU优势较少
iOS GPU较CPU优势较少
Android vivoX20(运行10次平均)
CPU:770ms,GPU:270
GPU较CPU快2.85倍
三星S7(运行10次平均)
CPU:982ms,GPU:174ms
GPU较CPU快5.64倍

 

 2.4、使用GPGPU意义:
GPU与CPU数据传输过程,与GPU实际运算耗时相当,所以使用GPU运算传输成本过高,实测在Android中具有较大优势。
本测试案例是从webAR项目中抽取,需要实时跟踪用户摄像头处理视频流(256*256),使用GPU计算意义非常大,否则无法实现实时跟踪。

 

三、如何实现GPU通用计算?

3.1、首先,我们通过一张流程图,演示原理:

3.2、实现:

3.2.1、创建顶点着色器,只是传递了贴图坐标。

1 attribute vec4 position;
2 varying vec2 vCoord;
3 void main() {
4     vCoord = position.xy * 0.5 + 0.5;
5     gl_Position = position;
6 }

3.2.2、创建片元着色器,根据贴图坐标贴图。

1 precision highp float;
2 varying vec2 vCoord;
3 uniform sampler2D map;
4 void main(void) {
5     vec4 color = texture2D(map, vCoord);
6     gl_FragColor = color;
7 }

 3.3.3、根据如上着色器代码,创建程序对象,变量code是我们要传入的用于计算的代码。

 1 // 绑定并编译着色器程序
 2 var vertexShaderSource = \'...\';
 3 var fragmentShaderSource = \'...\' + code + \'...\';
 4 var vertexShader = gl.createShader(gl.VERTEX_SHADER);
 5 gl.shaderSource(vertexShader, vertexShaderSource);
 6 gl.compileShader(vertexShader);
 7 var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
 8 gl.shaderSource(fragmentShader, fragmentShaderSource);
 9 gl.compileShader(fragmentShader);                
10 
11 // 创建程序对象
12 var program = gl.createProgram();
13 gl.attachShader(program, vertexShader);
14 gl.attachShader(program, fragmentShader);
15 gl.linkProgram(program);
16 gl.useProgram(program);

3.3.4、传入顶点数据,创建一个面覆盖整个画布。

1 // 顶点数据传输
2 var vertices = new Float32Array([-1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0]);
3 var vertexBuffer = gl.createBuffer();
4 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
5 gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
6 var aPosition = gl.getAttribLocation(program, \'position\');
7 gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);
8 gl.enableVertexAttribArray(aPosition);

3.3.5、传入原始数据,本例中传入我要处理的图像数据,作为贴图,最终绘制到屏幕。

 1 var gl = this.gl;
 2 var program = this.program;
 3 var texture = gl.createTexture();
 4 var uMap = gl.getUniformLocation(program, \'map\');
 5 
 6 gl.activeTexture(gl.TEXTURE0);
 7 gl.bindTexture(gl.TEXTURE_2D, texture);
 8 
 9 
10 
11 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
12 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
13 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
14 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
15 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
16 gl.generateMipmap(gl.TEXTURE_2D);
17 
18 gl.uniform1i(uMap, 0);                
19 
20 // 绘制
21 gl.clearColor(0, 0, 0, 1);
22 gl.clear(gl.COLOR_BUFFER_BIT);
23 gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);

3.3.6、从最终绘制的画面上,获取颜色信息作为最终处理结果数据。

1 var pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);
2 gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

3.3.7、完整代码:
http://tgideas.qq.com/2018/brucewan/gpu.js

其实清楚原理后,整体实现比较简单。
但是对于不了解WebGL的同学来说,理解上有一定难度,我后续准备写一个系列的WebGL教程,有兴趣的同学可以关注。

 

四、有无现成类库?

大家可以看到,我实现的gpu.js中,并没有将javascript转换成着色器语言(类C),而是用户直接传入着色器代码。但是github上已有将javascript转换为着色器语言的库。
https://github.com/gpujs/gpu.js

为什么我没有直接使用呢?
1、简单的使用,2k可以实现的代码,不想引入200k的库;
2、数据输入输出可以由自己灵活控制;
3、着色器语言很简单,特别只是使用基础运算逻辑的代码,没必要由库从Javascript转换。

没有WebGL基础的同学,建议直接使用https://github.com/gpujs/gpu.js,从本文理解整体逻辑;
有一定基础的同学,建议由http://tgideas.qq.com/2018/brucewan/gpu.js自己定制,更为灵活。
另外,这个组件我没打算深度封装,也没打算维护……嗯,就这样。

 

以上是关于CPU和GPU的运算机制的差异的主要内容,如果未能解决你的问题,请参考以下文章

CPU,GPU,NPU的架构差异对比

使用 cpu 与 gpu 进行训练的 pytorch 模型精度之间的巨大差异

使用和不使用 GPU 进行编程的语法差异?

GPU结构与CUDA系列1GPU与CPU比较:GPU介绍设计差异计算流程

GPU, CUDA,cuDNN三者的关系总结

GPU编程之: GPUvsCPU