Performance 性能问题:单CPU核心与单CUDA核心

Performance 性能问题:单CPU核心与单CUDA核心,performance,cuda,gpgpu,convolution,Performance,Cuda,Gpgpu,Convolution,我想比较单个Intel CPU内核和单个nVidia GPU内核(即:单个CUDA代码、单个线程)的速度。我确实实现了以下简单的2d图像卷积算法: 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_wi

我想比较单个Intel CPU内核和单个nVidia GPU内核(即:单个CUDA代码、单个线程)的速度。我确实实现了以下简单的2d图像卷积算法:

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;
        }
    }
}
无效卷积\u cpu(uint8\u t*res、uint8\u t*img、uint32\u t img\u宽度、uint32\u t img\u高度、uint8\u t*krl、uint32\u t krl\u宽度、uint32\u t krl\u高度)
{
int32_t center_x=krl_width/2;
int32_t center_y=krl_高度/2;
国际贸易总额;
int32_t fkx,fky;
int32_t xx,yy;
浮点数krl_和=0;
对于(uint32_t i=0;i=0&&yy<(int32_t)img_高度和&xx>=0&&xx<(int32_t)img_宽度)
{
总和+=img[yy*img_宽度+xx]*krl[fky*krl_宽度+fkx];
}
}
}
res[y*img\u width+x]=和*nc;
}
}
}
CPU和GPU的算法都是相同的。我还制作了另一个GPU版本,与上面的版本几乎相同。唯一的区别是,在使用
img
krl
数组之前,我将它们传输到共享内存中

我使用了两幅尺寸分别为52x52的图像,获得了以下性能:

  • CPU:10毫秒
  • GPU:1338ms
  • GPU(smem):1165ms
CPU为Intel Xeon X5650 2.67GHz,GPU为nVidia Tesla C2070

为什么我会有如此大的性能差异?看起来单个CUDA内核对于这个特定代码的速度要慢100倍!有人能给我解释一下原因吗?我能想到的原因是

  • CPU的更高频率
  • CPU进行分支预测
  • CPU是否有更好的缓存机制 您认为造成这种巨大性能差异的主要问题是什么


    请记住,我想比较单个CPU线程和单个GPU线程之间的速度。我不是在评估GPU的计算性能。我知道这不是在GPU上进行卷积运算的正确方法。

    我想解释一下,也许它对你有用

    CPU作为主机,GPU作为设备

    要在GPU上运行线程,CPU将所有数据(计算+将在其上执行计算的数据)复制到GPU。此复制时间始终大于计算时间。因为计算是在算术和逻辑单元ALU中进行的。这只是一些说明。但是复制需要更多的时间

    所以,当您在CPU中只运行一个线程时,CPU的所有数据都在自己的内存中,有缓存,还有分支预测、预取、微操作重新排序,L1速度快10倍,L2速度快10倍,每个周期多调度6倍指令,核心频率快4.6倍

    但是,当您想要在GPU上运行线程时,它首先将数据复制到GPU内存中。这一次需要更多的时间。其次,GPU内核在一个时钟周期内运行线程网格,但为此,我们需要对数据进行分区,以便每个线程访问一个数组项。在您的示例中,它是img和krl数组

    nvidia GPU还提供了一个探查器。如果代码中存在诸如“打印输出”或“打印”之类的代码,请删除这些代码,然后尝试分析exe。它将以毫秒为单位显示复制时间和计算时间

    循环并行化:当您运行两个循环来使用image\u width和image\u height计算映像时,需要更多的时钟周期才能执行,因为在指令级它通过计数器运行。但是当你把它们移植到GPU上时,你会使用threadid.x和threadid.y以及16或32个线程组成的网格,这些线程在GPU的一个内核中只运行一个时钟周期。这意味着它在一个时钟周期内计算16或32个数组项,因为它有更多的ALU。(如果没有依赖关系,并且数据分区良好)

    在卷积算法中,您在CPU中维护了循环,但在GPU中,如果您运行相同的循环,则不会受益,因为GPU 1线程将再次充当CPU 1线程。还有内存缓存、内存复制、数据分区等的开销


    我希望这能让您理解……

    为什么速度会慢5-10倍?您正在比较两种非常不同的多线程体系结构。GPU完全依赖SIMD(或SIMT)算法。仅使用一个线程来评估GPU的计算能力是完全没有意义的……这种“5-10倍的速度”是错误的。我会移除它。我不是在评估GPU的计算能力。也许我在第一篇文章中不是很清楚。我试图理解为什么单个CUDA内核和单个CPU内核之间存在如此巨大的性能差异。将CPU上的1个线程与GPU上的1个线程进行比较,这意味着只有1个1 SM的warp调度程序。CPU核心出现故障,具有分支预测、预取、微操作重新排序功能,L1速度快10倍,L2速度快10倍,每个周期多调度6倍指令,核心频率快4.6倍。费米体系结构没有针对单线程性能进行优化。如果合并所有内存操作,则将线程数增加到32是可用的。由于延迟隐藏,将扭曲计数增加到8-12/SM也几乎是免费的。感谢BenC和Greg的回复。所以,如果我们假设我的GPU只有一个CUDA内核,我不认为代码中真的有什么错误,对吗?事实上,CPU更为复杂,它们都有各自的处理器