我有一个 CUDA 内核,其中有很多操作和很少的分支。看起来像
__global__
void kernel(Real *randomValues, Real mu, Real sigma)
{
int row = blockDim.y * blockIdx.y + threadIdx.y;
int col = blockDim.x * blockIdx.x + threadIdx.x;
if ( row >= cnTimeSteps || col >= cnPaths ) return;
Real alphaLevel = randomValues[row*cnPaths+col];
Real q = 0.0;
Real x = 0.0;
if ( alphaLevel < p_low)
{
q = sqrt( -2*log( alphaLevel ) );
x = (((((c1*q+c2)*q+c3)*q+c4)*q+c5)*q+c6) / ((((d1*q+d2)*q+d3)*q+d4)*q+1);
}
else if ( alphaLevel < p_high )
{
q = alphaLevel-0.5;
Real r = q*q;
x= (((((a1*r+a2)*r+a3)*r+a4)*r+a5)*r+a6)*q / (((((b1*r+b2)*r+b3)*r+b4)*r+b5)*r+1);
}
else
{
q = sqrt( -2*log( 1.0-alphaLevel ) );
x = -(((((c1*q+c2)*q+c3)*q+c4)*q+c5)*q+c6) / ((((d1*q+d2)*q+d3)*q+d4)*q+1);
}
randomValues[row*cnPaths+col] = sigma * x + mu;
}
其中所有的a
's, b
's, c
's 和d
's 都是常量值(在设备常量内存中)
static __device__ __constant__ Real a1 = 1.73687;
static __device__ __constant__ Real a2 = 1.12321100;
等等。
在分析内核后,我发现理论占用率为 100%,但我得到的不超过 60%。
一方面,IPC 报告平均发出 1.32 条指令,执行 0.62 条指令。指令序列化大约是 50%,但 SM 活动几乎是 100%。另一方面,大约有 38 个活动扭曲,但有 8 个有资格执行下一条指令,但在扭曲问题效率方面,我得到大约 70% 的周期没有符合条件的扭曲。失速原因被报告为“其他”,我认为这与log
and的计算有关sqrt
。
- 如果大多数周期都没有符合条件的扭曲,那么 SM 活动如何达到 99.82%?
- 我怎样才能减少失速?
- 由于 warp 中的线程可能不会进入同一个分支,因此对常量内存的请求可能会被序列化,这是真的吗?我应该把这些常量放在全局内存中(也许也使用共享内存)吗?
我是第一次使用 Nsight Visual Studio,所以我试图弄清楚所有性能分析的含义。顺便说一句,我的卡是 Quadro K4000。