-2

私は次の簡単なC++コードを書きました。

#include <iostream>
#include <omp.h>

int main()
{
    int myNumber = 0;
    int numOfHits = 0;

    cout << "Enter my Number Value" << endl;
    cin >> myNumber;

    #pragma omp parallel for reduction(+:numOfHits)

    for(int i = 0; i <= 100000; ++i)
    {
        for(int j = 0; j <= 100000; ++j)
        {
            for(int k = 0; k <= 100000; ++k)
            {
                if(i + j + k == myNumber)
                    numOfHits++;
            }
        }
    }

    cout << "Number of Hits" << numOfHits << endl;

    return 0;
}

ご覧のとおり、OpenMPを使用して最も外側のループを並列化します。私がやりたいのは、この小さなコードをCUDAで書き直すことです。どんな助けでも大歓迎です。

4

1 に答える 1

1

簡単なチュートリアルを提供することはできますが、必ずしもすべてを記述するわけではありません。

まず最初に、CUDA を使用して MS Visual Studio をセットアップする必要があります。これは、次のガイドに従って簡単に行うことができます。 -cuda-easier-with-rc2/

ここで、NVIDIA CUDA プログラミング ガイド (無料の pdf)、ドキュメント、および CUDA by Example (CUDA の学習に強くお勧めする本) を読みたいと思うでしょう。

しかし、まだそれを行っておらず、間違いなく後で行うとしましょう。

これは非常に演算量が多く、データ量が少ない計算です。実際には、このブルート フォース法を使わなくてもかなり簡単に計算できますが、それはあなたが探している答えではありません。カーネルには次のようなものをお勧めします。

__global__ void kernel(int* myNumber, int* numOfHits){

    //a shared value will be stored on-chip, which is beneficial since this is written to multiple times
    //it is shared by all threads
    __shared__ int s_hits = 0;

    //this identifies the current thread uniquely
    int i = (threadIdx.x + blockIdx.x*blockDim.x);
    int j = (threadIdx.y + blockIdx.y*blockDim.y);
    int k = 0;

    //we increment i and j by an amount equal to the number of threads in one dimension of the block, 16 usually, times the number of blocks in one dimension, which can be quite large (but not 100,000)
    for(; i < 100000; i += blockDim.x*gridDim.x){
        for(; j < 100000; j += blockDim.y*gridDim.y){
                  //Thanks to talonmies for this simplification
               if(0 <= (*myNumber-i-j) && (*myNumber-i-j) < 100000){
                  //you should actually use atomics for this
                 //otherwise, the value may change during the 'read, modify, write' process
                  s_hits++;
               }
        }
    }

    //synchronize threads, so we now s_hits is completely updated
    __syncthreads();

    //again, atomics
    //we make sure only one thread per threadblock actually adds in s_hits
    if(threadIdx.x == 0 && threadIdx.y == 0)
        *numOfHits += s_hits;

    return;
}

カーネルを起動するには、次のようなものが必要です。

dim3 blocks(some_number, some_number, 1); //some_number should be hand-optimized
dim3 threads(16, 16, 1);
kernel<<<blocks, threads>>>(/*args*/);

おそらくこれを行うための簡単な方法が必要なのはわかっていますが、CUDA を使用することは実際には「簡単」なことではありません。のように、それを機能させるには、いくつかの読み取りとセットアップを行う必要があります。それを過ぎると、学習曲線はそれほど高くありません。メモリの割り当てについてはまだ何も説明していないので、それを行う必要があります (簡単ですが)。私のコードに従った場合、私の目標は、共有メモリと CUDA について少し読む必要があることです。したがって、あなたはすでにキックスタートしています。幸運を!

免責事項: 私は自分のコードをテストしておらず、専門家でもありません。ばかげている可能性があります。

于 2012-06-17T03:58:12.860 に答える