Cuda 快速数学运算

Cuda 快速数学运算,cuda,Cuda,这是我的密码 __device__ void calculateDT(float *devD, int *devImg, int cntVoxelLi, int *neighVoxels) { float minV = devD[cntVoxelLi]; int cv = devImg[cntVoxelLi]; float v = 0,cuVal = 0; int c1=0,d1=0,r1=0; GetInd2Sub(cntVoxelLi, r1,c

这是我的密码

    __device__ void calculateDT(float *devD, int *devImg, int cntVoxelLi, int *neighVoxels)
   {
    float minV = devD[cntVoxelLi];
   int cv = devImg[cntVoxelLi];
   float v = 0,cuVal = 0;
   int c1=0,d1=0,r1=0;
   GetInd2Sub(cntVoxelLi, r1,c1,d1);

   for(int ind=0;ind<9;ind++)
   {
    v = pow(float(cv - devImg[neighVoxels[ind]]),2);
    cuVal = devD[neighVoxels[ind]]  + (1-exp(-v/100));
    minV = min(minV, cuVal);
   }
   devD[cntVoxelLi] = minV;
   }

只需要7秒钟。似乎这个exp操作需要很多时间。我也尝试使用expf函数。如何提高性能?

您看到的性能差异主要是编译器优化的结果。当您删除
exp
表达式时,变量
v
将变得未使用,编译器将删除
v
的计算,因为它实际上是死代码。因此,执行时间的大幅下降是由于消除了内核循环中的所有浮点计算,而不仅仅是删除了
exp
函数

至于性能优化,最明显的一点是不使用
pow
来计算简单的平方(编译器可能自己也在这样做),并整理所有浮点表达式以消除大量隐式整数浮点转换(提示:0是整数,0.是双精度,0.f是单精度)


从您发布的代码中很难对内核中的内存事务性能进行评论。CUDA 4 visual profiler具有一些有用的诊断功能,可以显示一段代码是内存受限还是算术受限。您可能会发现分析代码并查看它报告的内容很有用。

您看到的性能差异主要是编译器优化的结果。当您删除
exp
表达式时,变量
v
将不被使用,编译器将删除
v
的计算,因为它实际上是死代码。因此,执行时间的大幅下降是由于消除了e内核循环,而不仅仅是从
exp
函数中删除

至于性能优化,最明显的一点是不使用
pow
来计算简单的平方(编译器可能自己也在这样做),并整理所有浮点表达式以消除大量隐式整数浮点转换(提示:0是整数,0.是双精度,0.f是单精度)

从您发布的代码中很难对内核中的内存事务性能进行评论。CUDA 4 visual profiler具有一些有用的诊断功能,可以显示一段代码是内存受限还是算术受限。您可能会发现分析代码并查看它报告的内容很有用。

也可以尝试使用“v/100”而不是“v/100”“v*1e-2”。请注意,这会略微更改数值结果,因此编译器无法自动执行该转换,因为它不是标识转换。您可以尝试使用_expf()而不是expf()。只要expf()的参数的大小较小(例如,小于4),expf()和_expf()之间的数值差异就不会太大将非常小。__expf()中的ulp错误大致随参数绝对值的对数而增长。您也可以尝试使用“v*1e-2”代替“v/100”“。请注意,这会略微更改数值结果,因此编译器无法自动执行该转换,因为它不是标识转换。您可以尝试使用_expf()而不是expf()。只要expf()的参数的大小较小(例如,小于4),expf()和_expf()之间的数值差异就不会太大。”是相当小的,_expf()中的ulp错误大致随参数绝对值的对数增长。
     exp(-v/100)