質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
CUDA

CUDAは並列計算プラットフォームであり、Nvidia GPU(Graphics Processing Units)向けのプログラミングモデルです。CUDAは様々なプログラミング言語、ライブラリ、APIを通してNvidiaにインターフェイスを提供します。

Q&A

1回答

656閲覧

CUDAのカーネル内における過剰なメモリ確保について

koume80703

総合スコア0

CUDA

CUDAは並列計算プラットフォームであり、Nvidia GPU(Graphics Processing Units)向けのプログラミングモデルです。CUDAは様々なプログラミング言語、ライブラリ、APIを通してNvidiaにインターフェイスを提供します。

0グッド

0クリップ

投稿2023/01/16 03:24

前提

CUDAを用いてMCTSにおけるシミュレーションの並列化処理を目指しています。MCTSを実装する対象としてBridgetというマイナーなボードゲームを用いています。

実現したいこと

  • ゲームの合法手探索によって得られた合法手を格納する配列を長さ3000にて宣言したい。
  • 宣言の際に、メモリの確保が過剰に行われているのを確認できたため、その過剰に確保される原因が知りたい。

発生している問題・エラーメッセージ

  • 合法手を格納する配列laを宣言する際に確保されるメモリがGPUの持つメモリ量10018[MiB]より大きくなってしまうため、メモリ外アクセスのエラーを吐いてしまう。
  • 配列laは大きさ3000のAction_cu型の配列であるため、Action_cuの大きさが56であることを考えると、単純計算で3000 * 56 = 168000[B]のメモリ使用で済むはずである。
  • 実際に確保されているメモリ量が膨大になっていることが考えられる。

以下コンパイル後の実行にて得られた出力結果が以下になります。メモリ外アクセスを起こしているとのエラーメッセージを確認できます。

$ nvcc -O2 -lcurand -I./header -g -G -o obj/kernel.o -c src/kernel.cu $ nvcc -O2 -lcurand -I./header obj/state.o obj/action.o obj/piece.o obj/measuring.o obj/board.o obj/ucb1.o obj/node.o obj/game.o obj/mcts.o obj/cell.o obj/argmax.o obj/main.o obj/trans_data.o obj/kernel.o obj/playout_cuda.o -o bin/bridget $ ./bin/bridget Error: src/playout_cuda.cu:44, code:2, reason: out of memory

該当のソースコード

C++

1typedef struct _Piece_cu { 2 int kind; 3 int rdx; 4 int rdy; 5 6 int rcs[3][3]; 7} Piece_cu; 8 9typedef struct _Action_cu { 10 // どのような一手であるのかを示す構造体 11 // sizeof(Action_cu)にて大きさを測ったところ56であった。 12 int x, y; 13 14 Piece_cu piece; 15} Action_cu; 16 17__device__ int playout_gpu(State_cuda *sc, curandState *s) { 18 while (1) { 19 *** 割愛 *** 20 21 Action_cu la[3000]; // 合法手を格納したい配列を宣言している。 22 23 *** 割愛 **** 24 } 25}

試したこと

  • 配列laのメモリ使用量が膨大であることが原因であるため、少しずつ大きくすることで実際にどれくらいの使用量となっているのか計測することが可能なのではないかと考えた。
  • Action_cu la[X]のXを少しずつ大きくしていき、実際にメモリ使用量がどのように変化したのかnvidia-smiを用いて計測した。
配列の大きさX1101001000
メモリ使用量[MiB]3393898935193
  • これによって分かるのが、配列の大きさ1あたりで確保されるメモリサイズが5.6[MiB]となっていることである。
  • 5.6[MiB]は本来の56[B]と比較すると約10^6倍もの差があることから明らかに不自然な挙動となっている。

バージョン等について

  • OS: Ubuntu 20.04.2 LTS
  • CUDA Version: 11.3
  • GPU: GeForce RTX3080

最後に

こちらのサイトでの質問が初めてなことから書くべき情報が足りていないかもしれません。その際、必要な情報を追記させていただきますので、連絡いただけると幸いです。回答の程よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

matukeso

2023/01/16 03:32

総スレッド数は幾つ? 1スレッドあたり158KBで、1e6個thraadを発生させれば158GB必要になる
koume80703

2023/01/16 03:54

返信ありがとうございます。 並列数のことでしたら、デバッグの段階ですので1並列にて実行しております。
matukeso

2023/01/16 05:06

playout_gpu<<<1,1,0,stream>>>(sc,s)ってこと?
koume80703

2023/01/16 05:56

dim3 block(threads_per_block, 1, 1); dim3 grid((n_elem + block.x - 1) / block.x, 1, 1); kernel<<<grid, block>>>(省略); という形で実行しております。threads_per_block, n_elemともに1として実行しています。kernelはホスト側から最初に呼び出す関数として定義しており、そのkernel内からplayout_gpu関数を呼び出しております。 情報記載不足で申し訳ありません。
jbpb0

2023/01/16 10:35 編集

> 1並列にて実行 それを2, 4と増やしたら、配列の大きさ1あたりで確保されるメモリサイズも2倍、4倍になるのでしょうか?
guest

回答1

0

CUDAのSTACK(レジスタからあふれた分)は、GlobalMemoryに確保されますが、いくつ確保されるかというと、「そのデバイスの最大スレッド数」固定です。
たとえば、RTX3080だと、multiProcessorCount=68で、maxThreadsPerMultiProcessor=1536だと、102912個のスタックフレームが個確保されます。

投稿2023/01/16 10:12

matukeso

総合スコア1590

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

koume80703

2023/01/16 10:27

私自身の理解が浅く申し訳ないのですが、スタックとは今回確保したい配列laのことでそれが最大スレッド数分だけ確保されるためにメモリを多く食ってしまっているという解釈でよろしいのでしょうか?意図した確保されるべきメモリ量に対して約10万倍ものメモリが確保されていることからmatukeso様のおっしゃる102912個のスタックフレームの確保が影響しているのではないかと思います。
matukeso

2023/01/16 11:08

laが小さければレジスタに載りますが、今のサイズだとその通りですね。 どうしてもというのであれば、外部からスレッド数に応じたlaを与える手です。
koume80703

2023/01/16 13:37

laのサイズは3000の長さを想定しており、その大きさは168000[B]なのですが、レジスタとはそれほどまでに小さいものなのでしょうか?GPUの仕様書を見ればそのレジスタの大きさはわかりますでしょうか?
matukeso

2023/01/16 14:29

deviceQueryすればわかりますが、最近のGPUではMultiProcessorあたり65536個、レジスタはあります(256KB)。これを実行中のスレッドが共有します。スレッドが少ない時でも、1スレッドあたりではmax255個とかです。 ふつうはたくさんスレッドを生やすので、30個とか、おおく使って128個とかになるでしょう。 shared memoryもMultiProcessorあたり48KB〜64KB程度ありますが。 laならまあ、スレッドあたりなんとか2、3個載せれるくらいですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問