如何比较CPU与GPU上程序如何被cpu执行的执行时间

2327人阅读
图片处理(3)
今天讨论的论题是CPU和GPU“擅长和不擅长”的各个方面,而不是谁取代谁的问题。我试着从它们执行运算的速度与效率的方面来探讨这个论题。
CPU和GPU都是具有运算能力的芯片,CPU更像“通才”——指令运算(执行)为重+ 数值运算,GPU更像“专才”——图形类数值计算为核心。在不同类型的运算方面的速度也就决定了它们的能力——“擅长和不擅长”。芯片的速度主要取决于三个方面:微架构,主频和IPC(每个时钟周期执行的指令数)。
从微架构上看,CPU和GPU看起来完全不是按照相同的设计思路设计的,当代CPU的微架构是按照兼顾“指令并行执行”和“数据并行运算”的思路而设计,就是要兼顾程序执行和数据运算的并行性、通用性以及它们的平衡性。CPU的微架构偏重于程序执行的效率,不会一味追求某种运算极致速度而牺牲程序执行的效率。
CPU微架构的设计是面向指令执行高效率而设计的,因而CPU是计算机中设计最复杂的芯片。和GPU相比,CPU核心的重复设计部分不多,这种复杂性不能仅以晶体管的多寡来衡量,这种复杂性来自于实现:如程序分支预测,推测执行,多重嵌套分支执行,并行执行时候的指令相关性和数据相关性,多核协同处理时候的数据一致性等等复杂逻辑。
GPU其实是由硬件实现的一组图形函数的集合,这些函数主要用于绘制各种图形所需要的运算。这些和像素,光影处理,3D 坐标变换等相关的运算由GPU硬件加速来实现。图形运算的特点是大量同类型数据的密集运算——如图形数据的矩阵运算,GPU的微架构就是面向适合于矩阵类型的数值计算而设计的,大量重复设计的计算单元,这类计算可以分成众多独立的数值计算——大量数值运算的线程,而且数据之间没有像程序执行的那种逻辑关联性。
GPU微架构复杂度不高,尽管晶体管的数量不少。从应用的角度看,如何运用好GPU的并行计算能力主要的工作是开发好它的驱动程序。GPU驱动程序的优劣很大程度左右了GPU实际性能的发挥。
因此从微架构上看,CPU擅长的是像操作系统、系统软件和通用应用程序这类拥有复杂指令调度、循环、分支、逻辑判断以及执行等的程序任务。它的并行优势是程序执行层面的,程序逻辑的复杂度也限定了程序执行的指令并行性,上百个并行程序执行的线程基本看不到。GPU擅长的是图形类的或者是非图形类的高度并行数值计算,GPU可以容纳上千个没有逻辑关系的数值计算线程,它的优势是无逻辑关系数据的并行计算。
另外,GPU执行每个数值计算的速度并没有比CPU快,从目前主流CPU和GPU的主频就可以看出了,CPU的主频都超过了1GHz,2GHz,甚至3GHz,而GPU的主频最高还不到1GHz,主流的也就500~600MHz。要知道1GHz = 1000MHz。所以GPU在执行少量线程的数值计算时并不能超过CPU。
目前GPU数值计算的优势主要是浮点运算,它执行浮点运算快是靠大量并行,但是这种数值运算的并行性在面对程序的逻辑执行时毫无用处。
3.IPC(每个时钟周期执行的指令数)
这个方面,CPU和GPU无法比较,因为GPU大多数指令都是面向数值计算的,少量的控制指令也无法**作系统和软件直接使用。如果比较数据指令的IPC,GPU显然要高过CPU,因为并行的原因。但是,如果比较控制指令的IPC,自然是CPU的要高的多。原因很简单,CPU着重的是指令执行的并行性。
另外,目前有些GPU也能够支持比较复杂的控制指令,比如条件转移、分支、循环和子程序调用等,但是GPU程序控制这方面的增加,和支持操作系统所需要的能力CPU相比还是天壤之别,而且指令执行的效率也无法和CPU相提并论。
最后总结一下:
CPU擅长的:操作系统,系统软件,应用程序,通用计算,系统控制等等;游戏中人工智能,物理模拟等等;3D建模-光线追踪渲染;虚拟化技术——抽象硬件,同时运行多个操作系统或者一个操作系统的多个副本等等。
GPU擅长的:图形类矩阵运算,非图形类并行数值计算,高端3D游戏。
综上所述,在一台均衡计算的计算机系统中,CPU和GPU还是各司其职,除了图形运算,GPU将来可能主要集中在高效率低成本的高性能并行数值计算,帮助CPU分担这种类型的计算,提高系统这方面的性能。而当前的典型应用还是高端3D游戏,一个高效的GPU配合一个高效的CPU,3D游戏的整体效率才能得到保证。“高端3D游戏只需要高端显卡”或者“高端3D游戏只需要CPU”都是无稽之谈。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:53718次
排名:千里之外
原创:29篇
转载:21篇
(1)(1)(5)(1)(4)(3)(25)(10)只需一步,快速开始
查看: 2674|回复: 7
同样功能程序 在 基于Nvidia GPU的Opencl运行时间为何比在CPU上还长
测试环境: 软件: windows8 , visual studio 2010, opencl 1.*; 硬件:CPU I7-4700MQ 2.4GHz,GPU NVIDIA GT 755M
程序功能: 单精度浮点型, 矩阵C =&&矩阵A + 矩阵B; 使用2D的计算方式,local size: 32 x 8
分布用不同size的测试结果:
ROI: 128 x 128
CPU For loop time: 0.024376 ms
Get Platform Time: 351.215901 ms
Set Context&&Time: 48.686936 ms
Set Command&&Time: 0.011547 ms
Read .cl File&&Time: 0.197148 ms
Build Program&&Time: 4.308597 ms
Three Buffer Copy&&Time: 0.154810 ms
Set Kernel Arg&&Time: 0.000428 ms
Run Kernel&&Time: 0.287382 ms
Buffer Copy Time: 0.100071 ms
******************************************************************************* GPU Opencl Time
Opencl Total Time: 404.962820
ROI: 256 x 256
CPU For loop time: 0.090662 ms
Get Platform Time: 0.000855 ms
Set Context&&Time: 49.718861 ms
Set Command&&Time: 0.011547 ms
Read .cl File&&Time: 0.119743 ms
Build Program&&Time: 0.680823 ms
Three Buffer Copy&&Time: 0.234781 ms
Set Kernel Arg&&Time: 0.000428 ms
Run Kernel&&Time: 0.594009 ms
Buffer Copy Time: 0.130862 ms
*******************************************************************************
Opencl Total Time: 51.491908
ROI: 512 x 512
CPU For loop time: 0.765498 ms
Get Platform Time: 0.002994 ms
Set Context&&Time: 54.743349 ms
Set Command&&Time: 0.012830 ms
Read .cl File&&Time: 0.174910 ms
Build Program&&Time: 0.717173 ms
Three Buffer Copy&&Time: 0.835205 ms
Set Kernel Arg&&Time: 0.000855 ms
Run Kernel&&Time: 1.803410 ms
Buffer Copy Time: 0.426369 ms
*******************************************************************************
Opencl Total Time: 58.717094
ROI: 1024 x 1024
CPU For loop time: 2.515023 ms
Get Platform Time: 0.004277 ms
Set Context&&Time: 51.468815 ms
Set Command&&Time: 0.011547 ms
Read .cl File&&Time: 0.135993 ms
Build Program&&Time: 0.694080 ms
Three Buffer Copy&&Time: 2.987152 ms
Set Kernel Arg&&Time: 0.000855 ms
Run Kernel&&Time: 4.977018 ms
Buffer Copy Time: 1.458722 ms
*******************************************************************************
Opencl Total Time: 61.738458
因为之前一直用CUDA,所以对nvidia GPU CUDA的运行速度还是有把握。现在是才开始使用Opencl,经过这次简单程序的测试,遇到一些疑惑,希望能得到论坛各位的解答,不胜感激。
问题1:Opencl 和有CUDA一样刚开始运行有初始化时间,这点可以理解;比如这里OPencl里面的Get Platform Time 和Build Program&&Time,这两个时间第一次很耗时,后面都不怎么耗时,这个可以理解。但是创建Context和设置设备 Set Context&&Time却每次都有,但是还是非常耗时,这是怎么回事?如果每次context设置都这么耗时,那OPENCL岂不是就不适合运行小数据处理的程序了?
问题2:Opencl每运行一个不同kernel都需要读取其cl文件的信息,还有其它buildProgma之类的时间损耗,这样每次都有固定的时间损耗,这些多余的时间又该如何处理呢,还是说无法避免呢?
问题3:Opencl GPU Kernel&&Run Kernel Time的运行时间居然没有CPU的运行时间快,这意味着使用opencl运行GPU的效率还不如CPU自己运行的时间?还是说我程序写法有问题,导致Opencl Kernel程序运行程序效率有问题?(因为我测试时间的数据的size都是用的128的倍数,所以应该不会存在内存读取不对齐而更耗时的问题)
线程规格设置:
size_t szx = 32;
& & size_t szy = 8;
& & size_t szLocal[2] = {szx, szy};
& & size_t szGlobal[2] = {((iW - 1) / szx + 1) * szx, ((iH - 1) / szy + 1)&&* szy};
& & clStatus = clEnqueueNDRangeKernel(clCommandQueue, clKernel, 2, NULL, szGlobal, szLocal, 0, NULL, NULL);
Opencl Kernel 运行:
__kernel void MatrixPointMul_Kernel(__global float&&const *cl_pfSrcA,
& && && && && && && && && && && && &__global float&&const *cl_pfSrcB,
& && && && && && && && && && && && &__global float& && &&&*cl_pfDstC,
& && && && && && && && && && && && && && && &int& & const&&iW,
& && && && && && && && && && && && && && && &int& & const&&iH
& && && && && && && && && && && && &)
& & uint uiBaseX = get_global_id(0);
& & uint uiBaseY = get_global_id(1);
& & uint uiSrcDstId = uiBaseY * iW + uiBaseX;
& & if(uiBaseX & iW && uiBaseY & iH)
& && &&&cl_pfDstC[uiSrcDstId] = cl_pfSrcA[uiSrcDstId] + cl_pfSrcB[uiSrcDstId];
1:OpenCL根据其平台的不同,适用于大量数据的并行(GPU)或是大量任务的并行(CPU)。但是如果任务量太小就要评估下到底有没有必要使用(这里可能还要考虑诸如跨平台之类的问题)。
2:这个问题可以通过预编译内核代码得到设备内核二进制代码进行缓存,这样就无需每次都重新编译内核了(只在当前平台发生变化后再重新编译)。
3:首先,你这个程序中访存其实占了绝对部分时间(计算指令的密度比例自然很低),这种带宽型的程序本来对CPU的优势就不大;其次,你程序写的确实低效,优化后纵有差别也不至于这么大。最后,计算量相对也比较小。
要根据需求的不同选择使用GPU还是CPU,不要总是以为用了GPU就一定比CPU快,实际中的很多问题CPU比充分优化后的GPU程序快的也比比皆是
本帖最后由 chenmoumou 于
15:13 编辑
1:OpenCL根据其平台的不同,适用于大量数据的并行(GPU)或是大量任务的并行(CPU)。但是如果任务量太小就要 ...
谢谢您的回答。
1.按照您的回答,OPenCL可能更适合大量数据的并行,那么目前移动端的Opencl岂不是发挥不出太大效果。您还说opencl也适合大量任务并行,其功能是不是和CPU多线程技术或者OPENMP类似,效率上呢?
3.上面的帖子我只是列举了Kernel运行的一种情况,实际上我还用过float4的访存方法,也修改过为1D的线程规模运行方式,不过最终效果也不尽人意。这个函数要对三个buffer进行读写,当然所有的时间都在访存上。这个kernel函数功能简单,就只是读取buffer,计算基本不耗时,所有不管是按照128Bit (float4)或者32Bit(float)访问,我觉得时间都不会有太大变化。根据我多年的CUDA编程经验,像这样简单的函数功能,排除COPY时间,就以我现在的硬件平台,对512 x 512 的数据而言,使用CUDA语言,GPU是肯定比单CPU快的。&&至于您提到的某些方面CPU比GPU快,这个我赞同,但是以现在这个函数而言,GPU运行如此之慢,不应该只是访存方面的问题。
谢谢您的回答。
1.按照您的回答,OPenCL可能更适合大量数据的并行,那么目前移动端的Opencl岂不是发挥不 ...
你找个A卡试试吧。
你找个A卡试试吧。
................看来是nvidia对opencl支持不够?
把你CPU段的完整代码贴上来看看呢
谢谢您的回答。
1.按照您的回答,OPenCL可能更适合大量数据的并行,那么目前移动端的Opencl岂不是发挥不 ...
我还说了你的程序优化不够,既然你有了多年的CUDA开发经验,那么应该知道你写的这个矩阵乘法的效率很低下,用充分优化过的CPU版矩阵乘法就可以超过,所以还是想想怎样你这个opencl内核程序优化吧。
我还说了你的程序优化不够,既然你有了多年的CUDA开发经验,那么应该知道你写的这个矩阵乘法的效率很低下 ...
我擦,大神。首先我这是矩阵相加,对于int或者float型的矩阵相加,我这样的代码写法,我真不知道还有什么方法来优化?一个线程处理几个点?还是ASM优化?不要告诉我用texture memory?求教大神,指点指点。
站长推荐 /1
为了更好地为各位会员提供技术支持服务,本论坛采用注册审核制度。您注册会员后,我们的管理人员会在8小时内在后台进行审核,审核通过会发邮件通知。只要是真实的开发者或学习者,我们都会审核通过。敬请谅解!如果您着急的话,可以发邮件至: 提醒我们第一时间审核通过。

我要回帖

更多关于 cpu是如何执行程序的 的文章

 

随机推荐