web-dev-qa-db-ja.com

共有メモリの割り当て

定数パラメーターを使用して共有メモリを割り当てようとしていますが、エラーが発生しています。私のカーネルは次のようになります。

__global__ void Kernel(const int count)
{
    __shared__ int a[count];
}

そして、私は言っているエラーが発生しています

エラー:式には定数値が必要です

カウントはconstです!このエラーが発生するのはなぜですか?そして、どうすればこれを回避できますか?

36
lina

constは「定数」を意味するのではなく、「読み取り専用」を意味します。

定数式は、その値がコンパイル時にコンパイラーに認識されるものです。

35

CUDAは、動的共有メモリ割り当てをサポートしています。このようにカーネルを定義する場合:

__global__ void Kernel(const int count)
{
    extern __shared__ int a[];
}

カーネル起動の3番目の引数として必要なバイト数を渡します

Kernel<<< gridDim, blockDim, a_size >>>(count)

その後、実行時にサイズを調整できます。ランタイムは、ブロックごとに動的に宣言された単一の割り当てのみをサポートすることに注意してください。さらに必要な場合は、その単一の割り当て内のオフセットへのポインターを使用する必要があります。また、共有メモリは32ビットワードを使用し、共有メモリの割り当てのタイプに関係なく、すべての割り当ては32ビットワードに揃える必要があることに注意してください。

84
talonmies

オプション1:定数値で共有メモリを宣言します(constとは異なります)

__global__ void Kernel(int count_a, int count_b)
{
    __shared__ int a[100];
    __shared__ int b[4];
}

オプション2:カーネル起動設定で共有メモリを動的に宣言します:

__global__ void Kernel(int count_a, int count_b)
{
    extern __shared__ int *shared;
    int *a = &shared[0]; //a is manually set at the beginning of shared
    int *b = &shared[count_a]; //b is manually set at the end of a
}

sharedMemory = count_a*size(int) + size_b*size(int);
Kernel <<<numBlocks, threadsPerBlock, sharedMemory>>> (count_a, count_b);

注:動的に共有されるメモリへのポインタは、同じアドレスを指定するとallになります。 2つの共有メモリアレイを使用して、共有メモリに2つのアレイを手動でセットアップする方法を説明します。

20
jmilloy

「CUDA Cプログラミングガイド」から:

実行構成は、次の形式の式を挿入することにより指定されます。

<<<Dg, Db, Ns, S>>>

どこ:

  • Dgはタイプdimであり、グリッドのサイズとサイズを指定します...
  • Dbdimタイプで、各ブロックの寸法とサイズを指定します...
  • Nsはタイプsize_tであり、静的に割り当てられたものに加えて、この呼び出しのブロックごとに動的に割り当てられた共有メモリ内のbytesの数を指定しますメモリ。この動的に割り当てられたメモリは、__ shared __で述べたように、外部配列として宣言された変数のいずれかによって使用されます。 Nsはオプションの引数で、デフォルトは0です。
  • SはcudaStream_tタイプで、関連するストリームを指定します...

そのため、動的パラメーターNsを使用することにより、ユーザーは、このカーネルに共有変数がいくつあっても、1つのカーネル関数が使用できる共有メモリの合計サイズを指定できます。

3
smh

このようなシェア変数は宣言できません。

__shared__ int a[count];

ただし、配列aの最大サイズについて十分に確信している場合は、次のように直接宣言できます

__shared__ int a[100];

しかし、この場合、共有メモリをブロックに固定する(そして完全に利用されない)ため、プログラムにブロックがいくつあるのか心配する必要があります。 ...

宣言するこの問題に対する素晴らしい解決策があります

extern __shared__ int a[];

そして、メモリからカーネルを呼び出している間にメモリを割り当てる

Kernel<<< gridDim, blockDim, a_size >>>(count)

ただし、カーネルで割り当てているよりも多くのメモリをブロックで使用している場合、予期しない結果が得られるため、ここでも気にする必要があります。

1
peeyush