我有两个内核:
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倍。为什么会这样?
答案 0 :(得分:2)
尽管代码上的差异似乎很小,但是如果您考虑一下,这里的两个内核将执行一些非常不同的计算。第一个内核仅用-1均匀填充缓冲区(编译器可以并且将只优化bodyPartPairsPtr
的负载,因为没有可观察到的行为取决于它们的结果)。第二个内核从内存中加载两个unsigned int
,然后用作偏移量来加载另外两个值,具体取决于它将向缓冲区写入-1还是不向缓冲区写入-1。因此,尽管第一个内核仅执行一个可能完美合并的存储,而第二个内核执行四个加载和一个从属存储。而且这忽略了细节,例如它还需要两个额外的恒定内存负载来获取额外的内核参数,这些参数在第一个内核中没有使用。从这个角度来看,第二个内核变慢并不奇怪。它只会产生更多的内存传输。
与性能问题一样,只有一种找到答案的方法:剖析。但是,如果您继续分析内核,我希望您发现它受内存传输的限制。而且很可能您会看到内存传输大约有4倍的差异,这可以解释您的结果……