关于程序的浮点运算能力的几点相关疑问

1.曾经发帖问了关于3.x的浮点运算峰值计算公式,横扫千军版主给我的回答是:N卡的峰值可以用SP频率(新的3.x上,这个频率就是GPU频率) * SP个数 * 2 得到,忘记问这个公式是单精度浮点运算峰值还是双精度浮点运算峰值,请您分别告诉我关于:单精度浮点运算峰值和双精度浮点运算峰值的两个公式。
2.在计算程序的浮点运算性能时候,譬如说cublas的矩阵乘法,我是这样计算的,对于1024x1024数据类型为float类型的矩阵乘法,我调用cublas进行计算,测得的时间假设为t ms,于是我得到浮点运算性能为(因为矩阵乘法无论算法如何,实际对元素的操作就是乘加操作):2x1024x1024x1024x1.0xe-9/(t/1000) (GFlops),我这样求得的浮点运算性能的方式对不对?请版主为我解惑,对于1024x1024数据类型为双精度类型的矩阵乘法(由于是双精度)又该怎样计算浮点运算性能,是不是一样的?(浮点运算性能和数据类型有怎样的关系?),请版主为我解惑。(这个问题来自于我计算1024x1024双精度矩阵乘法时,cublas运行时间为67.555ms,按照计算得到的浮点运算性能为31.789GFlops,而电脑的浮点运算峰值774.96GFlops,效率太低,我看别的文章cublas测得的运算性能是500多GFlops(输入数据为79MB数据),怀疑自己算的方法有问题)请版主为我解惑。

LZ您好:

本楼回答您的第一个问题:

关于浮点峰值的计算公式,横扫斑竹给您的是单精度的计算公式。

以及,如果您了解这个公式的来源,将可以自己进行推广。

该公式实质上是3部分相乘得到的,分别为计算单元频率,计算单元数量和指令吞吐量。
前两者很好理解,不再赘述;指令吞吐量这里是按照FMA算的,也就是每个SP,每周期可以有一条FMA指令的吞吐量,并且同时FMA因为同时计算了乘加,所以是两条浮点计算指令。

这样得到了GPU的理论单精度浮点峰值。
以及需要说明的是,并不是所有的单精度浮点计算都有这个峰值吞吐量,只有全部为FMA的情况,并且没有其他访存等方面的限制的情况下,并且在不考虑调度效率的情况下,才是这个峰值吞吐量。如果是其他吞吐量低的计算指令,自然达不到这个理论峰值。

回到双精度的情况,目前对于N卡来说,双精度浮点计算的单元是独立于单精度单元之外的,每个SP都有单精度的浮点计算单元,但并不是每个SP都有双精度的浮点单元。对于有双精度单元的SP而言,最大双精度指令吞吐量一样是在实现FMA的时候的每周期2条(指每周期一条双精度的FMA指令的吞吐量,FMA算作两条浮点操作)。

而具备双精度单元的SP数量(或者可用数量)与GPU架构以及产品线定位有关,具体为:

计算能力为1.3的GT200核心,第一次硬件支持双精度浮点计算,双精度峰值为单精度峰值的1/8,该核心目前已经基本退出使用。

GF100/GF110核心,有一半的SP具备双精度浮点单元,但是在geforce产品线中屏蔽了大部分的双精度单元而仅在tesla产品线中全部打开。代表产品有:tesla C2050,2075等,其双精度浮点峰值为单精度浮点峰值的一半;geforce GTX 480,580,其双精度浮点峰值为单精度浮点峰值的大约1/8左右。

其他计算能力为2.1的Fermi核心,原生设计中双精度单元数量较少,双精度计算峰值为单精度的1/12。

kepler GK110核心,原生的双精度浮点峰值为单精度的1/3,部分geforce产品线产品屏蔽了大部分的双精度峰值。代表产品有tesla系列的K20,K20X,K40他们都具备完整的双精度浮点峰值;geforce系列的geforce TITAN,此卡较为特殊,和tesla系列一样具备完整的双精度浮点峰值,geforce GTX780/780Ti,双精度浮点峰值受到屏蔽,具体情况不详,估计为单精度峰值的1/10左右。

其他计算能力为3.0的kepler核心,原生具备较少的双精度计算单元,双精度峰值为单精度峰值的1/24。

计算能力3.5的GK208核心,该卡的双精度效能不明,但是考虑到该核心定位于入门级别,大规模双精度计算无需考虑使用。

目前常见的各个GPU核心架构的双精度浮点峰值计算方法列举于此。

您可以从CUDA C Programming Guide中找到一个表格:Throughput of Native Arithmetic Instructions,您可以从中得到各个原生算数计算指令的按照SM统计的每周期的指令吞吐量,并予以计算,计算公式为SM/SMX数量*SM/SMX内SP的频率(kepler没有倍频,其他架构有倍频)*按SM折合的单周期指令吞吐量。

如果您打算简单估计的话,基本上除了geforce TITAN以外,其他所有geforce卡都不具备良好的双精度浮点的吞吐量,而本代的tesla K20/K20X/K40以及上一代的fermi核心的tesla卡是较好的选择。

您的第一个问题答复至此。

修订了个别叙述细节,修订后更为确切。

LZ的第二个问题在本楼答复:

1:无论单精度还是双精度,浮点计算的次数(FMA算两次浮点计算)/浮点计算的时间,就是对应精度下的浮点峰值吞吐量。换句话说,这个计算方法和单精度还是双精度无关,两者亦不能折算。

2:您对矩阵相乘的计算量估算基本是无误的,但是在GPU计算的时候这里的乘法和加法应该不能完全组合成乘加,同时整个计算中还有很多复杂的访存,所以您计算到的时间是总时间。由于cublas是闭源实现的,对用户而言是黑盒,所以亦无法详细判断其实现。

3:如果您计时没有问题,你呢可以根据2#中的介绍,研究一下您的GPU的双精度浮点计算吞吐量是多少,以及评估下cublas的性能如何,同时需要进一步测试一下在不同计算量下情况如何,避免因为计算量不够造成结果不准。关于cublas本身,并无更多建议。

大致如此,祝您好运~

1.谢谢ice版主详细的介绍,受益匪浅,我的笔记本显卡是Nvidia Geforce GT 750,看到您回复称“其他计算能力为3.0的kepler核心,双精度峰值为单精度峰值的1/24;由于电脑的单精度浮点峰值是774.96Gflops,是不是可以得到双精度峰值为32.29Gflops?我测了不同大小(512x512,1024x1024,2048x2048,4096x4096)矩阵乘法cublas实际的双精度浮点运算性能最高为31.948Gflops。这个值还是很不错的,很接近理论值,(我看的文章500多GFlops是单精度浮点型矩阵乘法,我下一步准备试试单精度浮点型是否能达到500多GFlops。)
2.对于您所说”GPU计算的时间这里的乘法和加法应该不能完全组合乘加“,我利用profiler测得1024x1024矩阵乘法Flops(Double):2149580800(这里应该指的就是乘加运算吧,实际理论乘加指令为2x1024x1024x1024=2.147484e9,这里怎么实际值还比理论值还多?请版主解惑)。
在Flops(Double Add)和Flops(Double Mul)为0,我以为乘加指令不是应该Flops(Double Add),Flops(Duoble Mul)指令之和吗,为什么这两个指令却为0,难道加法指令和乘法指令与乘加指令没有”半毛钱关系“?那么可不可以这样理解:有乘加直接一周期做完,只有乘法指令或加法指令也是一周期做完,所以统计将他们分开计数。

LZ您好:

1:感谢您反馈您的测试结果。以及这说明cublas的效率真不错。按照手册192sp的SMX每周期的双精度浮点加法/乘法/乘加的吞吐量只有8条的,而单精度的加法/乘法/乘加是192条,所以是1/24。

2:这里说“可能不能完全组合为乘加(的单一)指令”这个是我估计的,但是cublas可能有更好的实现方式,请您以实际情况为准。

另外,您这里比较的有些问题,您profiler的结果的单位是Flops(floating point operations per second)是一个速度概念,而您给出的理论值则为计算总量的概念,单位为floating point operations,两者量纲不同是不能直接比较的。

此外,FMA并非是Mul和Add组合而成的,如果是组合的,那么因为Mul和Add分别是每周期一条(对具有DP计算单元的SP而言)的吞吐量,FMA需要是每两个周期一条的吞吐量才行,而实际上,FMA(对于具有DP计算单元的SP)也是每周期一条的吞吐量,所以他们是分开的。

以及“有乘加直接一周期做完,只有乘法指令或加法指令也是一周期做完,所以统计将他们分开计数。”这个基本是正确的,他们吞吐量是一样的,但是统计指令次数和吞吐量高低无关。

大致如此,供您参考。

祝您好运~

以及补充说明一下,FAdd,FMul和FMA虽然在指令上是分开的统计的,但是在硬件实现上,有可能只设计一套FMA的硬件,而将前两者作为特殊情况进行计算。

但是N卡的设计细节是不公开的,因此我不能为您证实或者证伪这种可能性,列举于此,仅供您参考。

祝您编码顺利~

谢谢ice版主,看到你的回复中都有写道”SMX“,我知道SM称Stream Multiprocessor,SMX全称是什么?

LZ您好:

SMX中的X是extreme的意思,SMX是kepler 架构中SM的正式称谓,一般认为表示大量强化的含义。

因为您是kepler卡,所以上面写作SMX。

以及一般讨论中经常混用SM,SMX这两个名称而不加区分。

祝您编码顺利~

“另外,您这里比较的有些问题,您profiler的结果的单位是Flops(floating point operations per second)是一个速度概念,而您给出的理论值则为计算总量的概念,单位为floating point operations,两者量纲不同是不能直接比较的。”这里是我比较有误,谢谢版主提醒。

我用profiler测得1024x1024双精度矩阵乘法cublas运行时间为67.564ms,则浮点运算性能为:
(2x1024x1024x1024x1.0e-9)/(67.564x1.0e-3)=31.784GFlops,而profiler测得的Flops(Double)为:
2149580800即2.149580800GFlops,这怎么相差这么大,求版主解惑。

因为你再度弄错了单位!
Profiler的Flops是Floating point operations…没有除以时间(你可以自行除以时间的)。

感谢来访。

谢谢,是我错了,问题解决了,谢谢ice和玫瑰的耐心解答。

不客气的,欢迎您常来~

祝您编码顺利!