cuda - GPU 在 Julia 集合计算中没有提供性能改进

标签 cuda gpgpu gpu

我正在尝试比较 CPU 和 GPU 的性能。我有

  • CPU:Intel® Core™ i5 CPU M 480 @ 2.67GHz × 4
  • GPU:NVidia GeForce GT 420M

我可以确认 GPU 已配置并与 CUDA 一起正常工作。

我正在实现 Julia 集合计算。 http://en.wikipedia.org/wiki/Julia_set 基本上对于每个像素,如果坐标在集合中,它将把它涂成红色 否则把它漆成白色。

虽然,我在 CPU 和 GPU 上得到了相同的答案,但没有得到 性能提升,我通过使用 GPU 获得了性能损失。

运行时间

  • CPU:0.052 秒
  • GPU:0.784 秒

我知道将数据从设备传输到主机可能需要一些时间。 但是,我怎么知道使用 GPU 是否真的有益?

这里是相关的GPU代码

    #include <stdio.h>
    #include <cuda.h>

    __device__ bool isJulia( float x, float y, float maxX_2, float maxY_2 )
    {
        float z_r = 0.8 * (float) (maxX_2 - x) / maxX_2;
        float z_i = 0.8 * (float) (maxY_2 - y) / maxY_2;

        float c_r = -0.8;
        float c_i = 0.156;
        for( int i=1 ; i<100 ; i++ )
        {
        float tmp_r = z_r*z_r - z_i*z_i + c_r;
        float tmp_i = 2*z_r*z_i + c_i;

        z_r = tmp_r;
        z_i = tmp_i;

        if( sqrt( z_r*z_r + z_i*z_i ) > 1000 )
            return false;
        }
        return true;
    }

    __global__ void kernel( unsigned char * im, int dimx, int dimy )
    {
        //int tid = blockIdx.y*gridDim.x + blockIdx.x;
        int tid = blockIdx.x*blockDim.x + threadIdx.x;
        tid *= 3;
        if( isJulia((float)blockIdx.x, (float)threadIdx.x, (float)dimx/2, (float)dimy/2)==true )
        {
        im[tid] = 255;
        im[tid+1] = 0;
        im[tid+2] = 0;
        }
        else
        {
        im[tid] = 255;
        im[tid+1] = 255;
        im[tid+2] = 255;
        }

    }

    int main()
    {
        int dimx=768, dimy=768;

        //on cpu
        unsigned char * im = (unsigned char*) malloc( 3*dimx*dimy );

        //on GPU
        unsigned char * im_dev;

        //allocate mem on GPU
        cudaMalloc( (void**)&im_dev, 3*dimx*dimy ); 

        //launch kernel. 
**for( int z=0 ; z<10000 ; z++ ) // loop for multiple times computation**
{
        kernel<<<dimx,dimy>>>(im_dev, dimx, dimy);
}

        cudaMemcpy( im, im_dev, 3*dimx*dimy, cudaMemcpyDeviceToHost );

        writePPMImage( im, dimx, dimy, 3, "out_gpu.ppm" ); //assume this writes a ppm file

        free( im );
        cudaFree( im_dev );
    }

这是CPU代码

    bool isJulia( float x, float y, float maxX_2, float maxY_2 )
    {
        float z_r = 0.8 * (float) (maxX_2 - x) / maxX_2;
        float z_i = 0.8 * (float) (maxY_2 - y) / maxY_2;

        float c_r = -0.8;
        float c_i = 0.156;
        for( int i=1 ; i<100 ; i++ )
        {
        float tmp_r = z_r*z_r - z_i*z_i + c_r;
        float tmp_i = 2*z_r*z_i + c_i;

        z_r = tmp_r;
        z_i = tmp_i;

        if( sqrt( z_r*z_r + z_i*z_i ) > 1000 )
            return false;
        }
        return true;
    }


    #include <stdlib.h>
    #include <stdio.h>

    int main(void)
    {
      const int dimx = 768, dimy = 768;
      int i, j;

      unsigned char * data = new unsigned char[dimx*dimy*3];

**for( int z=0 ; z<10000 ; z++ ) // loop for multiple times computation**
{
      for (j = 0; j < dimy; ++j)
      {
        for (i = 0; i < dimx; ++i)
        {
          if( isJulia(i,j,dimx/2,dimy/2) == true )
          {
          data[3*j*dimx + 3*i + 0] = (unsigned char)255;  /* red */
          data[3*j*dimx + 3*i + 1] = (unsigned char)0;  /* green */
          data[3*j*dimx + 3*i + 2] = (unsigned char)0;  /* blue */
          }
          else
          {
          data[3*j*dimx + 3*i + 0] = (unsigned char)255;  /* red */
          data[3*j*dimx + 3*i + 1] = (unsigned char)255;  /* green */
          data[3*j*dimx + 3*i + 2] = (unsigned char)255;  /* blue */
          }
        }
      }
}

      writePPMImage( data, dimx, dimy, 3, "out_cpu.ppm" ); //assume this writes a ppm file
      delete [] data


      return 0;
    }

此外,根据@hyde 的建议,我循环了仅计算部分以生成 10,000 张图像。不过,我懒得写所有这些图像。我正在做的只是计算。

这是运行时间

  • CPU:超过 10 分钟,代码仍在运行
  • GPU:1 米 14.765 秒

最佳答案

将评论转为回答:

要得到相关的数字,需要计算不止一张图像,所以执行时间至少在几秒或几十秒。此外,在结果中包含文件保存时间会增加噪音并隐藏实际的 CPU 与 GPU 差异。

获得真实结果的另一种方法是选择一个 Julia 集,该集有很多属于该集的点,然后将迭代次数增加到如此之高以至于仅计算一个图像就需要很多秒。然后只有一个计算设置,因此这可能是 GPU/CUDA 最有利的场景。

要衡量有多少开销,请将图像大小更改为 1x1 并将迭代限制更改为 1,然后计算至少需要几秒钟的足够图像。在这种情况下,GPU 可能会慢很多。

要获得与您的用例最相关的时间,请选择您真正要使用的图像大小和迭代次数,然后测量图像数,这两个版本的速度都一样快。这会给你一个粗略的经验法则来决定你应该在什么时候使用。

实际结果的替代方法,如果您只想获得一张图像:找到单个最坏情况图像的迭代限制,其中 CPU 和 GPU 速度相同。如果那么多或更多的迭代是有利的,请选择 GPU,否则选择 CPU。

关于cuda - GPU 在 Julia 集合计算中没有提供性能改进,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14602900/

相关文章:

cuda - 通过增加占用率来提高内核性能?

c++ - 将 GpuMat 复制到 CUDA 张量

c++ - 使用 GPU (C++/OpenCV) 显示文件中的图像

cuda - 共享内存库与 char 数组冲突

cuda - 如何让 nvcc CUDA 编译器进行更多优化?

OpenCL - 如何查询设备的 SIMD 宽度?

CUDA 和并行寻址位

c++ - 开始 OpenCL 教程?

math - GPU 上的高精度数学运算

cuda - 使用 NVIDIA GPU 计算 SDK 4.0 和 microsoft VC++ 2010 Express 无需 GPU 硬件即可执行简单的 CUDA 程序