主要内容gydF4y2Ba

测量和提高GPU性能gydF4y2Ba

开始使用GPU基准gydF4y2Ba

您可以使用各种在MATLAB进行基准测试gydF4y2Ba®gydF4y2Ba测量GPU的性能:gydF4y2Ba

  • 使用gydF4y2BagpuBenchgydF4y2Ba在MATLAB中央文件交换做各种测试,包括内存和计算密集型任务单和双精度。比较显卡的性能与计算卡。有关更多信息,请参见gydF4y2Ba//www.tatmou.com/matlabcentral/fileexchange/34080-gpubenchgydF4y2Ba。gydF4y2Ba

  • 使用gydF4y2Baparalleldemo_gpu_benchgydF4y2Ba脚本gydF4y2Ba测量GPU性能gydF4y2Ba获取信息在你的PCI总线速度,GPU内存读/写和峰值计算表演双精度矩阵计算。gydF4y2Ba

提高性能使用单精度计算gydF4y2Ba

你可以提高你的GPU的性能通过你在单精度而不是双精度计算。在CPU计算,另一方面,你不得到改善时从双切换到单精度。原因是大多数GPU卡是专为图形显示,要求单精度高的性能。gydF4y2Ba

典型的例子的计算适合GPU的单精度计算包括图像处理和机器学习,看到如。gydF4y2Ba//www.tatmou.com/content/dam/mathworks/tag-team/Objects/d/Deep_Learning_in_Cloud_Whitepaper.pdfgydF4y2Ba。然而,其他类型的计算,如线性代数问题,通常需要双精度加工。gydF4y2Ba

你可以得到一个性能改进的50倍单相比,双精度计算,根据GPU卡和核心的总数。高端计算卡片通常显示一个小的改进。您可以确定您的特定GPU的性能改进gydF4y2BagpuBenchgydF4y2Ba,请参阅gydF4y2Ba//www.tatmou.com/matlabcentral/fileexchange/34080-gpubenchgydF4y2Ba。gydF4y2Ba

对于一个综合性能NVIDIA的概述gydF4y2Ba®gydF4y2BaGPU卡,看到gydF4y2Bahttps://en.wikipedia.org/wiki/List_of_Nvidia_graphics_processing_unitsgydF4y2Ba。你可以计算单精度和双精度之间的性能改善的因素如下:gydF4y2Ba

  • 在上面的wiki页面找到GPU。gydF4y2Ba

  • 获得表示单引号和双精度性能值表。如果没有双精度GFLOPS值,假设比率是24 32 x慢双精度。gydF4y2Ba

  • 表示单精度GFLOPS值除以GFLOPS双精度值。gydF4y2Ba

请注意gydF4y2Ba

如果你有一个移动显卡在你的笔记本电脑,你可以使用这张卡片GPU计算。然而,笔记本GPU可能是比台式机更强大等效性能降低。gydF4y2Ba

提高性能的基本工作流程gydF4y2Ba

在MATLAB GPU计算的目的是加速应用程序。这个话题讨论基本概念和实践可以帮助你取得更好的性能在GPU上,这些GPU硬件的配置和最佳实践在你的代码。论述了实现难度和性能之间的权衡,并描述了您可以使用的标准使用gpuArray函数之间的选择,gydF4y2BaarrayfungydF4y2Ba、mex files或CUDA内核。最后,它描述了如何精确测量在GPU性能。gydF4y2Ba

将MATLAB代码转换为运行在GPU上时,最好先从MATLAB代码已经表现良好。而GPU和CPU有不同的性能特征,一般指南编写好的MATLAB代码也帮你写好GPU的MATLAB代码。第一步总是概要CPU代码。的行代码分析器显示花大部分时间在CPU上可能会那些你必须专注于GPU的代码。gydF4y2Ba

是简单的开始转换代码使用MATLAB支持gpuArray内置函数数据。金宝app这些功能需要gpuArray输入,GPU执行计算,并返回gpuArray输出。MATLAB函数的列表,支持gpuArray数据中发现金宝appgydF4y2Ba运行在GPU MATLAB函数gydF4y2Ba。一般来说,这些功能支持相同的参数和数据类型作为标准的MA金宝appTLAB函数计算CPU。gydF4y2Ba

如果您想要使用的所有功能是支持GPU,可能在GPU上运行代码调用一样简单金宝appgydF4y2BagpuArraygydF4y2Ba输入数据转移到GPU,电话gydF4y2Ba收集gydF4y2Ba检索从GPU完成后输出数据。在许多情况下,您可能需要对代码进行向量化,用MATLAB矩阵和向量代替循环标量操作操作。虽然vectorizing CPU通常是一个很好的实践,它通常是在GPU实现高绩效的关键。有关更多信息,请参见gydF4y2BaVectorize改进GPU性能gydF4y2Ba。gydF4y2Ba

先进的工具来提高性能gydF4y2Ba

甚至可能将输入转换为gpuArrays和vectorizing代码后,你的算法有操作,要么没有内置函数,或没有足够快以满足应用程序的需求。在这种情况下,你有三个主要的选项:使用gydF4y2BaarrayfungydF4y2Ba预编译应用程序的element-wise部分,利用GPU的库函数,或者编写一个定制的CUDA内核。gydF4y2Ba

如果你有一个纯粹element-wise函数,可以改善其性能,通过调用它gydF4y2BaarrayfungydF4y2Ba。的gydF4y2BaarrayfungydF4y2Ba函数在GPU以聪明元素MATLAB函数变成一个定制的CUDA内核,从而减少执行操作的开销。通常,应用程序的一个子集,可以使用gydF4y2BaarrayfungydF4y2Ba即使整个应用程序不能。这个例子gydF4y2Ba提高性能的Element-wise MATLAB®函数使用ARRAYFUN在GPU上gydF4y2Ba显示了该方法的基本概念;和例子gydF4y2Ba使用GPU ARRAYFUN蒙特卡罗模拟gydF4y2Ba展示了这一点是如何在模拟金融应用程序完成的。gydF4y2Ba

MATLAB提供了一个广泛的并行计算工具箱™GPU-enabled图书馆功能,图像处理工具箱™,信号处理工具箱™,和其他产品。下载188bet金宝搏然而,有许多图书馆的附加功能,没有直接内置类似物在MATLAB的GPU的支持。金宝app例子包括NVIDIA性能图元库和CURAND图书馆,这些都包含在CUDA工具包附带MATLAB。如果你需要调用一个函数在其中的一个库,可以使用GPU墨西哥人接口。这个接口允许您从MATLAB gpuArrays提取设备数据的指针,这样您就可以通过这些GPU的指针函数。你可以返回值转换成gpuArrays回到MATLAB。更多信息见gydF4y2Ba运行包含CUDA MEX-Functions代码gydF4y2Ba。gydF4y2Ba

最后,您可以编写一个定制的CUDA内核的操作需要。这样可以直接集成到内核MATLAB使用CUDAKernel对象。gydF4y2Ba

这个例子gydF4y2Ba说明三种方法GPU计算:了曼德尔勃特集合gydF4y2Ba展示了如何实现一个简单的计算使用本节提到的三个方法。这个例子以MATLAB代码很容易转换为运行在GPU,重写代码使用gydF4y2BaarrayfungydF4y2Baelement-wise操作,最后展示了如何整合一个定制的CUDA内核相同的操作。gydF4y2Ba

或者,您可以编写一个CUDA内核的一部分MEX-file,称之为MEX-file内使用CUDA运行时API。这两种方法可能让你使用GPU的低级特征,如共享内存和纹理内存,没有直接可用的MATLAB代码。更多细节,请参见示例gydF4y2Ba访问高级CUDA功能使用墨西哥人gydF4y2Ba。gydF4y2Ba

提高性能的最佳实践gydF4y2Ba

硬件配置gydF4y2Ba

一般来说可以达到最好的性能当你GPU致力于计算。通常是不实际使用相同的GPU设备计算和图形,因为内存占用问题的合理规模和经常使用设备系统的图形。如果可能的话,获得一个单独的设备图形。为计算配置你的设备或图形的细节依赖于操作系统和驱动程序版本。gydF4y2Ba

在Windows上gydF4y2Ba®gydF4y2Ba系统,GPU设备可以在两种模式:Windows显示驱动模型(WDDM)或特斯拉计算集群(太极拳)模式。为获得最佳性能,任何设备用于计算应该在太极拳模式。咨询NVIDIA文档以了解更多的细节。gydF4y2Ba

NVIDIA的计算设备性能最高,特斯拉,支持错误校正码(ECC)当阅读和写作GPU内存。金宝appECC的目的是纠正偶尔bit-errors通常发生在读写动态内存。一种技术来提高性能是关掉ECC增加实现的内存带宽。虽然这样可以配置硬件,MathWorks不建议这种做法。的潜在损失精度由于沉默的错误可以比性能更有害。gydF4y2Ba

MATLAB编码实践gydF4y2Ba

本主题描述通用技术,帮助您在GPU实现更好的性能。其中一些建议适用于编写MATLAB代码时的CPU。gydF4y2Ba

MATLAB数组中的数据存储在列为主的秩序。因此,它有利于操作沿着第一或列数组的维数。如果一维数据远远超过其他人,你可能会取得更好的性能,如果你第一个维度。同样的,如果你经常在一个特定的维度,它通常是最好把它作为第一个维度。在某些情况下,如果连续操作目标不同维度的数组,它可能是有益的转置或排列这些操作之间的数组。gydF4y2Ba

gpu实现高性能并行计算许多结果。因此,矩阵和高维数组操作通常执行比操作矢量和标量。你可以取得更好的性能通过重写你的循环利用高维操作。修改循环的过程中,scalar-oriented代码使用MATLAB矩阵和向量操作称为向量化。更多细节,请参阅gydF4y2Ba使用向量化gydF4y2Ba。gydF4y2Ba

默认情况下,所有操作在MATLAB中执行双精度浮点运算。然而,大多数操作支持各种数据类型,包括整数和单精度金宝app浮点。今天的gpu和cpu执行单精确操作时,通常有更高的吞吐量和单精度浮点数据占用更少的内存。如果您的应用程序的单精度浮点精度要求允许使用,它可以大大提高MATLAB代码的性能。gydF4y2Ba

GPU的坐在称为PCI总线数据传输机制。虽然这总线是一种高效、高带宽的数据传输方式从电脑主机内存各种扩展卡,它仍然远低于整体的全局内存带宽的GPU设备或CPU(更多细节,请参见示例gydF4y2Ba测量GPU性能gydF4y2Ba)。此外,从GPU设备转移到MATLAB主机内存导致MATLAB等待设备上的所有等待操作完成之前执行其他语句。这可以显著影响应用程序的性能。一般来说,你应该限制你的次数MATLAB工作区和GPU之间传输数据。如果你可以传输数据到GPU的应用程序,执行所有的计算可以在GPU上,然后将结果返回到MATLAB最后,这通常导致最好的性能。同样,在可能的情况下它可以帮助创建数组直接在GPU上使用gydF4y2Ba“gpuArray”gydF4y2Ba或者是gydF4y2Ba“喜欢”gydF4y2Ba选择等功能gydF4y2Ba0gydF4y2Ba(例如,gydF4y2BaZ = 0 (___ gpuArray)gydF4y2Ba或gydF4y2BaZ = 0 (N,“喜欢”,g)gydF4y2Ba对现有gpuArraygydF4y2BaggydF4y2Ba)。gydF4y2Ba

在GPU度量性能gydF4y2Ba

测量在GPU性能的最佳方法是使用gydF4y2BagputimeitgydF4y2Ba。这个函数作为输入一个函数处理没有输入参数,并返回函数的执行时间来衡量。它负责等基准考虑重复定时操作获得更好的解决方案,执行功能,以免在测量初始化开销,并减去时间函数的开销。同时,gydF4y2BagputimeitgydF4y2Ba确保所有操作在GPU完成之前最后的时机。gydF4y2Ba

例如,考虑测量的时间计算gydF4y2Ba陆gydF4y2Ba随机矩阵的分解gydF4y2Ba一个gydF4y2Ba的大小gydF4y2BaNgydF4y2Ba——- - - - - -gydF4y2BaNgydF4y2Ba。您可以通过定义一个函数的gydF4y2Ba陆gydF4y2Ba分解和传递函数句柄gydF4y2BagputimeitgydF4y2Ba:gydF4y2Ba

兰德(N =gydF4y2Ba“gpuArray”gydF4y2Ba);跳频= @陆()(A);gputimeit (fh, 2);gydF4y2Ba% 2参数表示的输出gydF4y2Ba

你也可以测量性能gydF4y2Ba抽搐gydF4y2Ba和gydF4y2BatocgydF4y2Ba。然而,在GPU获得准确的时间,你必须在调用之前等待操作完成gydF4y2BatocgydF4y2Ba。有两种方法可以做到这一点。你可以叫gydF4y2Ba收集gydF4y2Ba在调用之前最后的GPU输出gydF4y2BatocgydF4y2Ba前:这就迫使所有的计算来完成测量。或者,您可以使用gydF4y2Ba等待gydF4y2Ba函数与一个gydF4y2BagpuDevicegydF4y2Ba对象作为输入。例如,如果你想测量时间计算gydF4y2Ba陆gydF4y2Ba矩阵的分解gydF4y2Ba一个gydF4y2Ba使用gydF4y2Ba抽搐gydF4y2Ba,gydF4y2BatocgydF4y2Ba,gydF4y2Ba等待gydF4y2Ba你能做到如下:gydF4y2Ba

gd = gpuDevice ();抽搐();陆[l u] =(一个);等待(gd);tLU = toc ();gydF4y2Ba

您还可以使用MATLAB分析器显示如何分布在GPU代码计算时间。注意,完成定时测量,分析器独立运行的每一行代码,所以它不能占重叠(异步)执行等可能发生在正常操作。整整时间算法,您应该使用gydF4y2Ba抽搐gydF4y2Ba和gydF4y2BatocgydF4y2Ba,或gydF4y2BagputimeitgydF4y2Ba(如上所述)。同时,用户定义的配置文件可能不会产生正确的结果墨西哥人如果他们运行异步功能。gydF4y2Ba

Vectorize改进GPU性能gydF4y2Ba

这个例子向您展示了如何提高性能通过运行一个函数在CPU、GPU而不是通过vectorizing计算。gydF4y2Ba

考虑执行快速卷积的一个函数的列矩阵。快速卷积,这是一个常见的操作在信号处理应用程序中,将每一列的数据从时域到频域,增加一个过滤器向量的变换,变换回时域,并将结果存储在一个输出矩阵。gydF4y2Ba

函数gydF4y2Bay = fastConvolution(数据、过滤器)[m, n] =大小(数据);gydF4y2Ba%在过滤器的列长度数据,和变换gydF4y2Bafilter_f = fft(过滤器,米);gydF4y2Ba% 0的创建一个数组大小和类一样的数据gydF4y2Bay = 0 (m, n,gydF4y2Ba“喜欢”gydF4y2Ba、数据);gydF4y2Ba%将每一列的数据gydF4y2Ba为gydF4y2Ba第九= 1:n af = fft(数据(:,ix));y (:, ix) =传输线(af。* filter_f);gydF4y2Ba结束gydF4y2Ba结束gydF4y2Ba

这个函数执行特定的CPU的数据大小,使用MATLAB和度量执行时间gydF4y2Ba时间gydF4y2Ba函数。的gydF4y2Ba时间gydF4y2Ba函数负责共同基准的注意事项,如占启动和开销。gydF4y2Ba

一个=复杂(randn (4096, 100), randn (4096、100));gydF4y2Ba%数据输入gydF4y2Ba1 b = randn(16日);gydF4y2Ba%滤波器输入gydF4y2Bac = fastConvolution (a, b);gydF4y2Ba%计算输出gydF4y2Bactime时间= (@ ()fastConvolution (a, b));gydF4y2Ba测量CPU时间百分比gydF4y2Badisp ([gydF4y2BaCPU = '的执行时间gydF4y2Banum2str (ctime)]);gydF4y2Ba

在样本的机器上,这段代码显示输出:gydF4y2Ba

CPU = 0.019335执行时间gydF4y2Ba

现在在GPU上执行这个函数。你可以很容易通过改变输入数据gpuArrays MATLAB数组而不是正常的。的gydF4y2Ba“喜欢”gydF4y2Ba语法使用在创建内部的输出函数确保gydF4y2BaygydF4y2Ba将gpuArray如果gydF4y2Ba数据gydF4y2Ba是一个gpuArray。gydF4y2Ba

ga = gpuArray(一个);gydF4y2Ba%将数组GPUgydF4y2Bagb = gpuArray (b);gydF4y2Ba%过滤器移动到GPUgydF4y2Bagc = fastConvolution (ga、gb);gydF4y2Ba%在GPU计算gydF4y2Bagtime = gputimeit (@ () fastConvolution (ga, gb));gydF4y2Ba%度量GPU时间gydF4y2Bagerr = max (max (abs(收集(gc) - c)));gydF4y2Ba%计算错误gydF4y2Badisp ([gydF4y2Ba对GPU的执行时间= 'gydF4y2Banum2str (gtime)]);disp ([gydF4y2Ba的最大绝对误差= 'gydF4y2Banum2str (gerr)]);gydF4y2Ba

在同一台机器上,这段代码显示输出:gydF4y2Ba

执行时间在GPU上的CPU执行时间= 0.019335 = 0.027235 = 1.1374 e-14最大绝对错误gydF4y2Ba

不幸的是,GPU比CPU慢这个问题。原因是gydF4y2Ba为gydF4y2Ba循环执行FFT、乘法和逆FFT操作单个列的长度为4096。最好的方法来提高性能是对代码进行向量化,这样一个MATLAB函数调用执行更多的计算。FFT和传输线操作很简单:进行向量化gydF4y2Bafft (A)gydF4y2Ba计算矩阵的每一列的FFTgydF4y2Ba一个gydF4y2Ba。您可以执行一个用过滤与每一列的矩阵使用MATLAB二进制标量扩展函数gydF4y2BabsxfungydF4y2Ba。矢量化函数是这样的:gydF4y2Ba

函数gydF4y2Bay = fastConvolution_v2(数据、过滤器)m =大小(数据,1);gydF4y2Ba%在滤波器的长度数据,和变换gydF4y2Bafilter_f = fft(过滤器,米);gydF4y2Ba%转换输入的每一列gydF4y2Ba房颤= fft(数据);gydF4y2Ba%每一列乘以计算逆滤波和变换gydF4y2Bay =传输线(bsxfun (@times,房颤,filter_f));gydF4y2Ba结束gydF4y2Ba

执行相同的实验使用矢量函数:gydF4y2Ba

一个=复杂(randn (4096, 100), randn (4096、100));gydF4y2Ba%数据输入gydF4y2Ba1 b = randn(16日);gydF4y2Ba%滤波器输入gydF4y2Bac = fastConvolution_v2 (a, b);gydF4y2Ba%计算输出gydF4y2Bactime时间= (@ ()fastConvolution_v2 (a, b));gydF4y2Ba测量CPU时间百分比gydF4y2Badisp ([gydF4y2BaCPU = '的执行时间gydF4y2Banum2str (ctime)]);ga = gpuArray(一个);gydF4y2Ba% GPU的移动数据gydF4y2Bagb = gpuArray (b);gydF4y2Ba%过滤器移动到GPUgydF4y2Bagc = fastConvolution_v2 (ga、gb);gydF4y2Ba%在GPU计算gydF4y2Bagtime = gputimeit (@ () fastConvolution_v2 (ga, gb));gydF4y2Ba%度量GPU时间gydF4y2Bagerr = max (max (abs(收集(gc) - c)));gydF4y2Ba%计算错误gydF4y2Badisp ([gydF4y2Ba对GPU的执行时间= 'gydF4y2Banum2str (gtime)]);disp ([gydF4y2Ba的最大绝对误差= 'gydF4y2Banum2str (gerr)]);gydF4y2Ba
执行时间在GPU上的CPU执行时间= 0.010393 = 0.0020537 = 1.1374 e-14最大绝对错误gydF4y2Ba

总之,vectorizing帮助两个CPU和GPU版本的代码运行得更快。然而,向量化有助于GPU的版本比CPU。改进的CPU版本几乎是原来的两倍;改进的GPU版本比原来的13倍。GPU的代码从低于40%的CPU在最初的版本中,在修改后的版本快5倍。gydF4y2Ba

故障排除gpugydF4y2Ba

如果你只有一个GPU在您的机器,那么很可能你的显卡也充当你的显卡。在这种情况下,你的GPU可能受到超时由操作系统(OS)。你可以检查这个GPU如下:gydF4y2Ba

gpuDevicegydF4y2Ba
ans =gydF4y2Ba
…gydF4y2Ba
KernelExecutionTimeout: 1gydF4y2Ba
如果gydF4y2BaKernelExecutionTimeout = 1gydF4y2Ba,那么你的GPU超时由操作系统,确保操作系统总是能够更新打印到屏幕上。如果你的GPU计算需要太多的时间,那么手术死亡。在这种情况下,您必须重新启动MATLAB成功恢复GPU的计算。gydF4y2Ba

另请参阅gydF4y2Ba

相关的话题gydF4y2Ba