CUDA:在if语句中,写入全局内存的速度很慢

时间:2018-09-01 21:05:59

标签: cuda

我有两个内核:

template <typename T>
__global__ void bpcKernel(T* finalOutputPtr, const T* heatMapPtr, const T* peaksPtrA, const T* peaksPtrB, const unsigned int* bodyPartPairsPtr, const unsigned int* mapIdxPtr, const int POSE_MAX_PEOPLE, const int TOTAL_BODY_PARTS, const int heatmapWidth, const int heatmapHeight)
{
    const auto i = (blockIdx.x * blockDim.x) + threadIdx.x;
    const auto j = (blockIdx.y * blockDim.y) + threadIdx.y;
    const auto k = (blockIdx.z * blockDim.z) + threadIdx.z;

    const T* bodyPartA = peaksPtrA + (bodyPartPairsPtr[i*2]*POSE_MAX_PEOPLE*3 + j*3);
    const T* bodyPartB = peaksPtrB + (bodyPartPairsPtr[i*2 + 1]*POSE_MAX_PEOPLE*3 + k*3);

    finalOutputPtr[i*POSE_MAX_PEOPLE*POSE_MAX_PEOPLE + j*POSE_MAX_PEOPLE + k] = -1;

    if(bodyPartA[2] >= 0.05 && bodyPartB[2] >= 0.05){
        //finalOutputPtr[i*POSE_MAX_PEOPLE*POSE_MAX_PEOPLE + j*POSE_MAX_PEOPLE + k] = -1;
    }
}

这会计算一条if语句,但是所有线程都会写入finalOutputPtr

    template <typename T>
__global__ void bpcKernel(T* finalOutputPtr, const T* heatMapPtr, const T* peaksPtrA, const T* peaksPtrB, const unsigned int* bodyPartPairsPtr, const unsigned int* mapIdxPtr, const int POSE_MAX_PEOPLE, const int TOTAL_BODY_PARTS, const int heatmapWidth, const int heatmapHeight)
{
    const auto i = (blockIdx.x * blockDim.x) + threadIdx.x;
    const auto j = (blockIdx.y * blockDim.y) + threadIdx.y;
    const auto k = (blockIdx.z * blockDim.z) + threadIdx.z;

    const T* bodyPartA = peaksPtrA + (bodyPartPairsPtr[i*2]*POSE_MAX_PEOPLE*3 + j*3);
    const T* bodyPartB = peaksPtrB + (bodyPartPairsPtr[i*2 + 1]*POSE_MAX_PEOPLE*3 + k*3);

    //finalOutputPtr[i*POSE_MAX_PEOPLE*POSE_MAX_PEOPLE + j*POSE_MAX_PEOPLE + k] = -1;

    if(bodyPartA[2] >= 0.05 && bodyPartB[2] >= 0.05){
        finalOutputPtr[i*POSE_MAX_PEOPLE*POSE_MAX_PEOPLE + j*POSE_MAX_PEOPLE + k] = -1;
    }
}

此线程执行相同的操作,但仅在满足这两个条件时才写。

但是由于某种原因,第二个内核要花6毫秒才能计算出来。它慢了将近4倍。为什么会这样?

1 个答案:

答案 0 :(得分:2)

尽管代码上的差异似乎很小,但是如果您考虑一下,这里的两个内核将执行一些非常不同的计算。第一个内核仅用-1均匀填充缓冲区(编译器可以并且将只优化bodyPartPairsPtr的负载,因为没有可观察到的行为取决于它们的结果)。第二个内核从内存中加载两个unsigned int,然后用作偏移量来加载另外两个值,具体取决于它将向缓冲区写入-1还是不向缓冲区写入-1。因此,尽管第一个内核仅执行一个可能完美合并的存储,而第二个内核执行四个加载和一个从属存储。而且这忽略了细节,例如它还需要两个额外的恒定内存负载来获取额外的内核参数,这些参数在第一个内核中没有使用。从这个角度来看,第二个内核变慢并不奇怪。它只会产生更多的内存传输。

与性能问题一样,只有一种找到答案的方法:剖析。但是,如果您继续分析内核,我希望您发现它受内存传输的限制。而且很可能您会看到内存传输大约有4倍的差异,这可以解释您的结果……