有人能提供示例代码来演示cuda中16位浮点的使用吗?
Cuda 7.5支持16位浮点变量。有人能提供示例代码来演示cuda中16位浮点的使用吗?,cuda,Cuda,Cuda 7.5支持16位浮点变量。 有人能提供示例代码来演示它的使用吗 有几件事需要事先注意: 参考半精度 请注意,大多数或所有这些内部函数仅在设备代码中受支持。(但是,@njuffa创建了一组主机可用的转换函数) 请注意,compute capability 5.2及以下版本的设备本机不支持半精度算法。这意味着任何要执行的算术运算都必须在某些支持的类型上执行,例如float。计算能力为5.3(目前为Tegra TX1)的设备和可能的未来设备将支持“本机”半精度算术运算,但这些运算目前通过\u
有人能提供示例代码来演示它的使用吗 有几件事需要事先注意:
float
。计算能力为5.3(目前为Tegra TX1)的设备和可能的未来设备将支持“本机”半精度算术运算,但这些运算目前通过\uuu hmul
等内部函数公开。在不支持本机操作的设备中,类似于\uuuuhmul
的内部代码将是未定义的cuda_fp16.h
包含在任何文件中,以便在设备代码中使用这些类型和内部函数浮点
数量,将其转换为半
数量,并按比例因子进行缩放:
$ cat t924.cu
#include <stdio.h>
#include <cuda_fp16.h>
#define DSIZE 4
#define SCF 0.5f
#define nTPB 256
__global__ void half_scale_kernel(float *din, float *dout, int dsize){
int idx = threadIdx.x+blockDim.x*blockIdx.x;
if (idx < dsize){
half scf = __float2half(SCF);
half kin = __float2half(din[idx]);
half kout;
#if __CUDA_ARCH__ >= 530
kout = __hmul(kin, scf);
#else
kout = __float2half(__half2float(kin)*__half2float(scf));
#endif
dout[idx] = __half2float(kout);
}
}
int main(){
float *hin, *hout, *din, *dout;
hin = (float *)malloc(DSIZE*sizeof(float));
hout = (float *)malloc(DSIZE*sizeof(float));
for (int i = 0; i < DSIZE; i++) hin[i] = i;
cudaMalloc(&din, DSIZE*sizeof(float));
cudaMalloc(&dout, DSIZE*sizeof(float));
cudaMemcpy(din, hin, DSIZE*sizeof(float), cudaMemcpyHostToDevice);
half_scale_kernel<<<(DSIZE+nTPB-1)/nTPB,nTPB>>>(din, dout, DSIZE);
cudaMemcpy(hout, dout, DSIZE*sizeof(float), cudaMemcpyDeviceToHost);
for (int i = 0; i < DSIZE; i++) printf("%f\n", hout[i]);
return 0;
}
$ nvcc -o t924 t924.cu
$ cuda-memcheck ./t924
========= CUDA-MEMCHECK
0.000000
0.500000
1.000000
1.500000
========= ERROR SUMMARY: 0 errors
$
$cat t924.cu
#包括
#包括
#定义DSIZE 4
#定义SCF 0.5f
#定义nTPB 256
__全局无效半刻度内核(float*din、float*dout、int-dsize){
int idx=threadIdx.x+blockDim.x*blockIdx.x;
if(idx=530
kout=uuhmul(亲属,scf);
#否则
kout=uuuu2float2half(uuu2float(kin)*uu2float(scf));
#恩迪夫
dout[idx]=\uuuu2半浮(kout);
}
}
int main(){
浮动*欣、*霍特、*丁、*杜特;
hin=(浮动*)malloc(DSIZE*sizeof(浮动));
hout=(float*)malloc(DSIZE*sizeof(float));
对于(inti=0;i
如果您研究上述代码,您会注意到,除了cc5.3和更高版本的设备外,该算法是作为常规的浮点操作进行的。这与上文注3一致
收获如下:
在cc5.2及以下的设备上,half
数据类型可能仍然有用,但主要是作为存储优化(以及相关的内存带宽优化,因为例如,给定的128位向量负载可以一次加载8half
数量)。例如,如果您有一个大型神经网络,并且您已经确定权重可以作为半精度量存储(从而使存储密度增加一倍,或者使可在GPU存储空间中表示的神经网络的大小大约增加一倍),然后可以将神经网络权重存储为半精度。然后,当您需要执行向前传球(推断)或向后传球(训练)时,您可以从内存中加载权重,动态地(使用内部函数)将它们转换为float
数量,执行必要的操作(可能包括因训练而调整权重),然后(如有必要)将重量再次存储为数量的一半
对于cc5.3和未来的设备,如果算法允许,则可以执行与上述类似的操作,但无需转换为浮点
(或者返回到half
),而是将所有数据保留在half
表示中,并直接执行必要的算法(例如使用\uu hmul
或\uu hadd
内部函数)
虽然我没有在这里演示,但是half
数据类型在主机代码中是“可用”的。我的意思是,您可以为该类型的项分配存储,并对其执行例如cudaMemcpy
操作。但是主机代码对half
数据类型一无所知(例如,如何对其进行算术运算、打印或进行类型转换)并且内部函数在主机代码中不可用。因此,如果需要,您当然可以为大量half
数据类型分配存储(可能存储一组神经网络权重),但您只能通过设备代码而不是主机代码轻松地直接操作该数据
还有几点意见:
CUBLAS库设计用于直接处理一半
数据。上面的描述应该可以让我们了解不同设备类型(即计算能力)的“机箱下”可能发生的情况
有关在推力中使用half
的相关问题如下
有几件事需要提前注意:
参考半精度
请注意,大多数或所有这些内部函数仅在设备代码中受支持。(但是,@njuffa创建了一组主机可用的转换函数)
请注意,计算能力为5.2及以下的设备本机不支持半精度算术。这意味着任何要执行的算术运算都必须在某些支持的类型上完成,例如float
。计算能力为5.3(当前为Tegra TX1)的设备和可能的未来设备将支持“本机”半精度算术运算,但这些运算目前是通过诸如\uuuuhmul
之类的内部函数公开的