Cuda GPU在Julia集计算中没有提供性能改进

Cuda GPU在Julia集计算中没有提供性能改进,cuda,gpgpu,gpu,Cuda,Gpgpu,Gpu,我试图比较CPU和GPU的性能。我有 CPU:英特尔®核心™ i5 CPU M 480@2.67GHz×4 GPU:NVidia GeForce GT 420M 我可以确认GPU已配置并与CUDA正常工作 我正在实现Julia集计算。 基本上,对于每个像素,如果坐标在集合中,它会将其绘制为红色 否则就把它漆成白色 虽然,我得到的答案与CPU和GPU完全相同,但并没有得到答案 性能改进,我使用GPU得到性能惩罚 运行时间 中央处理器:0.052s GPU:0.784s 我知道将数据从设备传

我试图比较CPU和GPU的性能。我有

  • CPU:英特尔®核心™ i5 CPU M 480@2.67GHz×4
  • GPU:NVidia GeForce GT 420M
我可以确认GPU已配置并与CUDA正常工作

我正在实现Julia集计算。 基本上,对于每个像素,如果坐标在集合中,它会将其绘制为红色 否则就把它漆成白色

虽然,我得到的答案与CPU和GPU完全相同,但并没有得到答案 性能改进,我使用GPU得到性能惩罚

运行时间

  • 中央处理器:0.052s
  • GPU:0.784s
我知道将数据从设备传输到主机可能需要一些时间。 但是,我怎么知道使用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 );
    }
#包括
#包括
__设备(浮点x,浮点y,浮点maxX_2,浮点maxY_2)
{
浮点数z_r=0.8*(浮点数)(maxX_2-x)/maxX_2;
浮动z_i=0.8*(浮动)(最大值2-y)/最大值2;
浮点数c_r=-0.8;
浮点数c_i=0.156;
对于(int i=1;i 1000)
返回false;
}
返回true;
}
__全局无效内核(无符号字符*im,int-dimx,int-dimy)
{
//int tid=blockIdx.y*gridDim.x+blockIdx.x;
int tid=blockIdx.x*blockDim.x+threadIdx.x;
tid*=3;
如果(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;
}
其他的
{
im[tid]=255;
im[tid+1]=255;
im[tid+2]=255;
}
}
int main()
{
int dimx=768,dimy=768;
//在cpu上
无符号字符*im=(无符号字符*)malloc(3*dimx*dimy);
//关于GPU
未签名字符*im_dev;
//在GPU上分配内存
Cudamaloc((无效**)和im_-dev,3*dimx*dimy);
//启动内核。

**对于(intz=0;z将注释转换为答案:

要获得相关数据,您需要计算多个图像,这样执行时间至少为秒或数十秒。此外,将文件保存时间包括在结果中会增加噪声并隐藏实际CPU与GPU的差异

获得真实结果的另一种方法是选择一个Julia集合,该集合有很多属于该集合的点,然后将迭代计数提高到只计算一个图像需要很多秒。然后只有一个计算设置,因此这可能是GPU/CUDA最有利的方案

要测量开销,请将图像大小更改为1x1,迭代限制为1,然后计算足够的图像,至少需要几秒钟。在这种情况下,GPU的速度可能会显著降低

要获得与您的用例最相关的计时,请选择您真正要使用的图像大小和迭代计数,然后测量图像计数,这两个版本的速度相同。这将为您提供一个粗略的经验法则,以决定何时使用哪个


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

您当然应该做一个测试,它的计算结果类似于1000个图像,而不是0第一,可能这样做并更新你的问题…并将保存的内容从内部循环中删除,计算出大约100兆字节的图像。“并将保存内容从内部循环中删除”。请澄清我的意思是,如果你想测量CPU-GPU的性能差异,那么最好不要在同一个循环中做其他事情…至少除非你可以在另一个线程中保存PPM,同时开始计算下一个映像,在这种情况下,你可能会从增加的并行性中获益。遵循你的建议我已经循环了计算循环。我想我很满意GPU确实工作得更快。推论正确吗?@mkuse:GTX420M是一个小芯片,它只有48个内核。相比之下,GTX480的内核数量是它的10倍。你可能最终无法补偿将数据从设备复制到主机的开销。有一些标杆吗我做过一个项目,其中涉及曼德尔布罗特的计算。
    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;
    }