多くの操作と少数の分岐がある 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% を超えていません。
カーネルを最適化するために、thisとthis GTC talks を実行しました。
一方では、IPC が平均 1.32 の発行された命令と 0.62 の実行された命令を報告していることを確認しました。命令のシリアル化は約 50% ですが、SM アクティビティはほぼ 100% です。一方、約 38 のアクティブなワープがありますが、8 つは次の命令を実行する資格がありますが、ワープ発行効率では、サイクルの約 70% に適格なワープがないことがわかります。log
ストールの理由は「その他」として報告されますが、これは と の計算に関係していると思いますsqrt
。
- ほとんどのサイクルに適格なワープがない場合、SM アクティビティが 99.82% になるにはどうすればよいでしょうか?
- ストールを減らすにはどうすればよいですか?
- ワープ内のスレッドは同じブランチに入らない可能性があるため、定数メモリへの要求はおそらくシリアライズされますが、これは本当ですか? これらの定数をグローバル メモリに配置する必要がありますか (共有メモリも使用する可能性があります)。
Nsight Visual Studio を使用するのは初めてなので、すべてのパフォーマンス分析の意味を理解しようとしています。ところで、私のカードは Quadro K4000 です。