web-dev-qa-db-ja.com

CUDAカーネルでホスト関数を呼び出す方法は?

次のエラーが示すように、カーネルではホスト関数( 'Rand')を呼び出すことは許可されていません。その必要がある場合は、解決策があるかどうか疑問に思います。

error: calling a Host function("Rand") from a __device__/__global__ function("xS_v1_cuda") is not allowed
13
Hailiang Zhang

残念ながら、__device__修飾子で指定されていないデバイスで関数を呼び出すことはできません。デバイスコードに乱数が必要な場合は、cudaランダムジェネレーターcurandhttp://developer.nvidia.com/curand を参照してください。 ==

カーネルから呼び出したい独自のホスト関数がある場合は、その上で__Host__修飾子と__device__修飾子の両方を使用します。

__Host__ __device__ int add( int a, int b )
{
    return a + b;
}

このファイルがNVCCコンパイラドライバーによってコンパイルされると、2つのバージョンの関数がコンパイルされます。1つはホストコードで呼び出し可能で、もう1つはデバイスコードで呼び出し可能です。これが、この関数をホストコードとデバイスコードの両方で呼び出すことができる理由です。

27
geek

簡単に言えば、ここではその問題の解決策はありません。

通常CPUで実行されるものはすべて、CUDA環境に合わせて調整する必要がありますが、それが可能であるという保証はありません。ホスト関数は、通常のC関数のCUDAの単なる別名です。つまり、すべてのC/C++のようなCPUメモリVonNeumannアーキテクチャで実行される関数は、これまでPCで使用されてきました。 GPUは、途方もない量の計算能力を提供しますが、コストは、柔軟性や互換性がほとんどないことです。最も重要なことは、関数がメインメモリにアクセスする機能なしで実行され、アクセスできるメモリが制限されていることです。

取得しようとしているのが乱数ジェネレーターである場合、NvidiaがSMPあたり最大256スレッドをサポートできる非常に効率的なメルセンヌツイスターを具体的に実装するのに苦労したことを考えると、幸運です。これは、私の以前の投稿で説明されているデバイス関数内で呼び出すことができます ここ 。この機能を説明するより良いリンクを見つけた場合は、私のものを削除し、リンクと一緒に適切なテキストをここに置き換えてください。

私が絶えず驚いていることの1つは、標準化された高品質の疑似乱数ジェネレーターがどれほどあるかを知らないプログラマーが多いことです。 「自分で転がす」というのは、芸術の疑似乱数がどれだけあるかを考えると、実際には良い考えではありません。許容できる予測不可能な数を提供するものとしてジェネレーターを検証するには、多くの作業と学術的才能が必要です...

7
opetrenko

'Rand()'には適用できませんが、計算互換性> = 2.0でコンパイルすると、「printf」などのいくつかのホスト関数を使用できます。

例えば:

nvcc.exe -gencode=Arch=compute_10,code=\sm_10,compute_10\...
error : calling a Host function("printf") from a __device__/__global__ function("myKernel") is not allowed

Sm_20、compute_20をコンパイルして処理します

5
ultracuda