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

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

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

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

Q&A

1回答

1501閲覧

CUDAで配列の総和を求めたい

pg-newbie

総合スコア0

CUDA

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

0グッド

0クリップ

投稿2022/07/23 17:43

前提

CUDAとCで非常に大きな一次元配列の総和を求めたいです。
double[100000000]のようなサイズです。

総和を求めるプログラムは下記URLをほぼそのまま使っています。
https://qiita.com/gyu-don/items/ef8a128fa24f6bddd342

下記コードだと配列数1048576までは総和を求められますが、
それ以上のサイズだと求めることができません。

大きな配列の総和を求めるようにするにはどのようにしたらよいのでしょうか。

CUDA(GPU)自体あまり理解できておらず、このような用途ではGPUはつかわないのか、
総和を求めるだけならCPUが早いのかなど一般的なCUDAの利用についても教えていただけるとたすかります。

該当のソースコード

C

1#include <stdio.h> 2 3__global__ void reduce0(double *g_idata, double *g_odata, unsigned int n){ 4 5 extern __shared__ double sdata[]; 6 7 unsigned int tid = threadIdx.x; 8 unsigned int i = blockIdx.x * blockDim.x + threadIdx.x; 9 10 sdata[tid] = (i < n) ? g_idata[i] : 0; 11 __syncthreads(); 12 13 for (unsigned int s=1; s<blockDim.x; s*=2) { 14 if (tid % (2*s) == 0) { 15 sdata[tid] += sdata[tid + s]; 16 } 17 __syncthreads(); 18 } 19 20 if (tid == 0) g_odata[blockIdx.x] = sdata[0]; 21 22} 23 24int main(int argc, char *argv[]){ 25 26 int threads_per_block = 1024; 27 int number_of_blocks = 1024; 28 29 //NG 30 unsigned int n = 1048577; 31 //OK 32 //unsigned int n = 1048576; 33 double array = n * sizeof(double); 34 double result = number_of_blocks * sizeof(double); 35 double *pt_array, *pt_result, cpu_result = 0.0, gpu_result = 0.0; 36 cudaMallocManaged(&pt_array, array); 37 cudaMallocManaged(&pt_result, result); 38 39 // Initialize 40 for(unsigned int i=0; i<n; i++){ 41 pt_array[i] = 2.0; 42 } 43 44 // CPU 45 for(unsigned int i=0; i<n; i++){ 46 cpu_result = cpu_result + pt_array[i]; 47 } 48 49 printf("cpu_result: %.1f\n", cpu_result); 50 51 cudaFuncSetAttribute(&reduce0, cudaFuncAttributeMaxDynamicSharedMemorySize, 163840); 52 reduce0<<< number_of_blocks, threads_per_block, 163840 >>>(pt_array, pt_result, n); 53 cudaDeviceSynchronize(); 54 55 for(int i=0; i<number_of_blocks; i++){ 56 gpu_result = gpu_result + pt_result[i]; 57 } 58 // GPU 59 printf("gpu_result: %.1f\n", gpu_result); 60 61 cudaFree(pt_array); 62 cudaFree(pt_result); 63 64}

試したこと

cudaFuncSetAttributeで共有メモリのサイズを拡張しました。

補足情報(FW/ツールのバージョンなど)

CUDA11.4で動作検証をしています。

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

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

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

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

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

episteme

2022/07/24 11:02

> 総和を求めるだけならCPUが早いのか CPU/GPUのふたつでやってみればいいじゃん
guest

回答1

0

number_of_blocksを相当に増やせばいい、というか、nとthreads_per_block から計算するのが筋。

C

1int number_of_blocks = ( n + threads_per_block -1 ) / threads_per_block ;

投稿2022/07/24 22:56

matukeso

総合スコア1590

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問