我想比较单个Intel CPU核心的速度与单个nVidia GPU核心(即:单个CUDA代码,单个线程)的速度。我确实实现了以下naive 2d图像卷积算法:性能问题:单个CPU核心与单个CUDA核心
void convolution_cpu(uint8_t* res, uint8_t* img, uint32_t img_width, uint32_t img_height, uint8_t* krl, uint32_t krl_width, uint32_t krl_height)
{
int32_t center_x = krl_width/2;
int32_t center_y = krl_height/2;
int32_t sum;
int32_t fkx,fky;
int32_t xx,yy;
float krl_sum = 0;
for(uint32_t i = 0; i < krl_width*krl_height; ++i)
krl_sum += krl[i];
float nc = 1.0f/krl_sum;
for(int32_t y = 0; y < (int32_t)img_height; ++y)
{
for(int32_t x = 0; x < (int32_t)img_width; ++x)
{
sum = 0;
for(int32_t ky = 0; ky < (int32_t)krl_height; ++ky)
{
fky = krl_height - 1 - ky;
for(int32_t kx = 0; kx < (int32_t)krl_width; ++kx)
{
fkx = krl_width - 1 - kx;
yy = y + (ky - center_y);
xx = x + (kx - center_x);
if(yy >= 0 && yy < (int32_t)img_height && xx >= 0 && xx < (int32_t)img_width)
{
sum += img[yy*img_width+xx]*krl[fky*krl_width+fkx];
}
}
}
res[y*img_width+x] = sum * nc;
}
}
}
该算法对于CPU和GPU都是相同的。我也做了另一个与上述几乎相同的GPU版本。唯一的区别是我在使用它们之前将img
和krl
阵列传输到共享内存。
我使用的尺寸52x52每2个图像和我得到了以下性能:
- CPU:10ms的
- GPU:1338ms
- GPU(SMEM):1165ms
的CPU是Intel Xeon X5650 2.67GHz,GPU是nVidia Tesla C2070。
为什么我会得到这样的性能差异?它看起来像一个CUDA核心是这个特定的代码慢100倍!有人可以向我解释为什么?我能想到的原因是
- CPU的频率更高
- 的CPU确实分支预测。
- CPU有更好的缓存机制吗?
你认为是造成这种巨大性能差异的主要问题?
请记住,我想比较单个CPU线程和单个GPU线程之间的速度。我不想评估GPU的计算性能。我知道这不是在GPU上进行卷积的正确方法。
为什么它会是唯一的5-10倍慢?您正在比较两种非常**不同的多线程体系结构。 GPU仅依赖于SIMD(或SIMT)算法。仅使用一个线程对评估GPU的计算能力毫无意义... – BenC
这种“慢5-10倍”是错误的。我将删除它。我不想评估GPU的计算能力。也许我在第一篇文章中不太清楚。我想了解为什么单个CUDA内核和单个CPU内核之间存在如此巨大的性能差异。 – AstrOne
比较CPU上的1个线程与GPU上的1个线程,这意味着只有1个SM的warp调度器。 CPU内核出现故障,具有分支预测,预取,微操作重新排序,L1速度提升10倍,L2速度提升10倍,每周期能够分派6倍指令,核心频率提高4.6倍。费米架构未针对单线程性能进行优化。如果所有内存操作合并,则将线程数增加到32是免费的。由于延迟隐藏,将经纱数量增加至8-12/SM也接近免费。 –