我想比較單個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也接近免費。 –