-2

cudaで計算するときは本当ですが、計算にもっと大きな数を使用するときは、
このリンクとしてTdrLevelを設定する必要があり ます。しかし、tdrlevelを設定した後、これとして間違った結果が得られます。(-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080- 431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080-431602080)

どこに問題があるのか​​わからない。私のブロックのカウントは 512 で、各ブロックのスレッドのカウントは 1024 です。私は私の平均を見つけることを願っています。


that's my program code for fibunatchi program it work without tdrlevel but have above result by tdrlevel :


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


__global__ void fibunat_array(float *a,int N )
{    
    for (int x=0; x< N; x += 1)
    {
        a[x]=0;
    }
    a[0]=1;a[1]=1;  
    for (int i=0; i< N; i += 1)
    {
        a[i+2]=a[i]+a[i+1];       
    }       
}

int main( void )
{
    time_t start,end;
    double dif;
    time ( &start );

    float *a_h,*a_d;
    const int N = 100;

    size_t size = N * sizeof( float );
    a_h = (float *)malloc( size );    

    cudaMalloc( (void **)&a_d, size );  
    cudaMemcpy( a_d, a_h, size, cudaMemcpyHostToDevice );

    int block_size = 9<<1;
    int n_blocks   = (N+ block_size-1) /block_size;
    square_array <<< n_blocks , block_size >>> ( a_d, N );
    cudaMemcpy( a_h, a_d, sizeof( float ) * N, cudaMemcpyDeviceToHost );

    for (int i = 0; i<N/3+10 ; i++)
        printf( "%d  ",(int)a_h[i] ); 

    free( a_h );
    cudaFree( a_d );


    time ( &end );
    dif=difftime(end,start);

    printf ( "\n\n");
    printf ( "total time for this calculate is : %d second\n\n",(int)dif);

}
4

1 に答える 1

1

このコードにはいくつかの問題があります。たとえば、1つの問題は、fibunat_arrayという名前でカーネルを定義しているのに、square_arrayという名前でカーネルを呼び出していることです。したがって、投稿したコードは正しくコンパイルされません。もう1つの問題は、スレッドを並列で実行することを考慮せずに、問題を解決するためにシリアルコードが何をするかという観点からカーネルが記述されていることです。カーネルの起動時に作成された各スレッドは、まったく同じコードを実行します。複数のスレッド/ブロックが使用されている場合、これは機能せず、マシンを利用するための良い方法ではありません。

あなたはフィボナッチ数列の最初の100個の数を計算したいと思っているようです。これの意味を検討することをお勧めします。このページが役立つかもしれません。たとえば、このシーケンス範囲の最大数の一部は、64ビット整数に収まりません。32ビットコードでは、シーケンス内の約47の数値の後、符号なし整数サイズが小さすぎます。また、並列fibonacciジェネレーターを作成するには、おそらく、考えているシリアルアルゴリズムに似ていないアルゴリズムが必要になります。

並列フィボナッチジェネレーターを作成し、各スレッドがシリーズの1要素を計算したと仮定すると、100要素以内で(64ビット)マシン解像度が不足します。これは、マシンから得られる最も並列性を意味します。 (これらの仮定の下で)100スレッド未満の価値があります。これは、シリアルアルゴリズムよりも高速化するという点で、おそらく満足のいく結果が得られないようなものを作成するための多くの作業です。一般的に、GPUは、何千ものスレッドを実行できる場合に最良の結果をもたらします。

そうは言っても、証拠としてだけなら、何かを機能させることができます。元の作業にはいくつかの問題があるため、正しい結果を生成するコードを提示する方が簡単です。これは私がGPUの賢明な使用法と呼ぶものではありませんが、元のコードにいくつかの小さな変更を加えることで、この方法で正しい結果を得ることができます。

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


__global__ void fib(float *a,int N )
{
    for (int x=0; x< N; x += 1)
    {
        a[x]=0;
    }
    a[0]=1;a[1]=1;
    for (int i=0; i< (N-2); i += 1)
    {
        a[i+2]=a[i]+a[i+1];
    }
}

int main( void )
{
//    time_t start,end;
//    double dif;
//    time ( &start );

    float *a_h,*a_d;
    const int N = 40;

    size_t size = N * sizeof( float );
    a_h = (float *)malloc( size );

    cudaMalloc( (void **)&a_d, size );
    cudaMemcpy( a_d, a_h, size, cudaMemcpyHostToDevice );

   //  int block_size = 9<<1;
   //  int n_blocks   = (N+ block_size-1) /block_size;
   fib<<<1,1>>> ( a_d, N ); // just one thread does all the work
   cudaMemcpy( a_h, a_d, sizeof( float ) * N, cudaMemcpyDeviceToHost );

   for (int i = 0; i<N ; i++)
     printf( "%d  ",(int)a_h[i] );

   printf("\n");
   free( a_h );
   cudaFree( a_d );


//    time ( &end );
//    dif=difftime(end,start);

//    printf ( "\n\n");
//    printf ( "total time for this calculate is : %d second\n\n",(int)dif);

}

タイミング部分をコメントアウトしました。必要に応じて、コメントを外すことができます。GPUで並列処理を使用していないため、タイミングは印象的ではありません。さらに、このコードにはさまざまな特性があります。最も明白なものの1つは、1つのスレッドのみを起動し、実際にはGPUをシリアルマシンとして使用していることです。これはGPUプログラミングを行う方法ではないため、これを有益な例として使用しないでください。CUDA SDKに含まれる優れたGPUプログラミングの例は数多くあり、Web上の他のさまざまなリソースもあります。

于 2012-10-06T02:39:12.297 に答える