3

CPUとGPUのパフォーマンスを比較しようとしています。私は持っています

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

GPUが構成され、CUDAで正しく動作することを確認できます。

ジュリア集合の計算を実装しています。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:1m 14.765s
4

1 に答える 1

3

コメントを回して答える:

関連する数値を取得するには、実行時間が少なくとも数秒または数十秒になるように、複数の画像を計算する必要があります。また、結果にファイル保存時間を含めると、ノイズが追加され、実際のCPUとGPUの違いが隠されます。

実際の結果を得るもう1つの方法は、セットに属するロットポイントを持つジュリア集合を選択し、反復回数を増やすと、1つの画像だけを計算するのに数秒かかることです。その場合、計算設定は1つしかないため、これがGPU/CUDAにとって最も有利なシナリオになる可能性があります。

オーバーヘッドの量を測定するには、画像サイズを1x1に変更し、反復制限を1にしてから、少なくとも数秒かかるのに十分な画像を計算します。このシナリオでは、GPUの速度が大幅に低下する可能性があります。

ユースケースに最も関連するタイミングを取得するには、実際に使用する画像サイズと反復回数を選択してから、画像数を測定します。どちらのバージョンも同じように高速です。これにより、どちらをいつ使用するかを決定するための大まかな経験則が得られます。

1つの画像のみを取得する場合の、実用的な結果の代替アプローチ:CPUとGPUが同等に高速である、単一の最悪の場合の画像の反復制限を見つけます。その数以上の反復が有利な場合はGPUを選択し、そうでない場合はCPUを選択します。

于 2013-01-30T13:05:25.100 に答える