0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GPUで1+1を計算する

0
Posted at

NVIDIA GPUを使って、CUDAで1+1を計算する最小限のコードを紹介します。Cは初心者なのでお手柔らかにお願いいたします。

環境

  • NVIDIA GPU(本記事ではGTX980Tiで動作確認)
  • CUDA Toolkit
  • Linux環境
details
~/workspace/my/gpu_test[0] > nvidia-smi   
Sun Dec 14 13:13:18 2025       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.274.02             Driver Version: 535.274.02   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce GTX 980 Ti      Off | 00000000:06:00.0  On |                  N/A |
| 26%   66C    P0              64W / 250W |    555MiB /  6144MiB |      0%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A      6394      G   /usr/lib/xorg/Xorg                          249MiB |
|    0   N/A  N/A      6676      G   cinnamon                                     48MiB |
|    0   N/A  N/A      7006      G   /usr/lib/firefox/firefox                    154MiB |
|    0   N/A  N/A    113302      G   /usr/share/cursor/cursor                     78MiB |
+---------------------------------------------------------------------------------------+
~/workspace/my/gpu_test[0] > uname -a                  
Linux goto 6.8.0-90-generic #91-Ubuntu SMP PREEMPT_DYNAMIC Tue Nov 18 14:14:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

コード全体

add.cu
#include <stdio.h>
#include <cuda_runtime.h>

__global__ void add(int *a, int *b, int *c) {
    *c = *a + *b;
}

int main(void) {
    int a = 1, b = 1, c = 0;
    int *d_a, *d_b, *d_c;
    int size = sizeof(int);

    cudaMalloc((void **)&d_a, size);
    cudaMalloc((void **)&d_b, size);
    cudaMalloc((void **)&d_c, size);

    cudaMemcpy(d_a, &a, size, cudaMemcpyHostToDevice);
    cudaMemcpy(d_b, &b, size, cudaMemcpyHostToDevice);

    add<<<1, 1>>>(d_a, d_b, d_c);

    cudaMemcpy(&c, d_c, size, cudaMemcpyDeviceToHost);

    printf("1 + 1 = %d\n", c);

    cudaFree(d_a);
    cudaFree(d_b);
    cudaFree(d_c);

    return 0;
}

コードの解説

1. ヘッダーファイル

#include <stdio.h>
#include <cuda_runtime.h>
  • stdio.h: 標準入出力(printf用)
  • cuda_runtime.h: CUDAランタイムAPI(GPU操作用)

cuda_runtime.hがない場合は

sudo apt install nvidia-cuda-toolkit -y

をインストールしてください。

2. GPUカーネル関数

__global__ void add(int *a, int *b, int *c) {
    *c = *a + *b;
}
  • __global__: GPUで実行されるカーネル関数を示す修飾子

    • __global__ は、この関数をGPUで実行することをコンパイラ(nvcc)に伝える修飾子です。

    __global__ がないと

    // __global__ がない場合
    void add(int *a, int *b, int *c) {
    *c = *a + *b;
    }
    

    この場合、add<<<1, 1>>>(d_a, d_b, d_c); という呼び出しができません。<<<>>> 構文は __global__ 関数にしか使えません。

  • 引数はすべてGPUメモリ上のポインタ

  • *c = *a + *b で加算を実行

3. メイン関数

1. 変数の宣言

int a = 1, b = 1, c = 0;
int *d_a, *d_b, *d_c;
int size = sizeof(int);
  • a, b, c: CPU側(ホスト)の変数。aは被加算子、bは加算子、cは和です。
  • d_a, d_b, d_c: GPU側(デバイス)のポインタ
  • size: 転送サイズ(int = 4バイト)

2. GPUメモリの確保

cudaMalloc((void **)&d_a, size);
cudaMalloc((void **)&d_b, size);
cudaMalloc((void **)&d_c, size);
  • cudaMalloc: GPU側にメモリを確保
  • 各変数用に4バイトずつ確保

3. データ転送:CPU → GPU

cudaMemcpy(d_a, &a, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_b, &b, size, cudaMemcpyHostToDevice);
  • cudaMemcpy: メモリコピー関数
  • cudaMemcpyHostToDevice: CPUからGPUへ転送
  • a=1, b=1 をGPUメモリに転送

4. GPUカーネルの実行

add<<<1, 1>>>(d_a, d_b, d_c);
  • <<<1, 1>>>: カーネル起動設定
    • 第1引数: ブロック数(1)
    • 第2引数: スレッド数/ブロック(1)
  • GPU上でadd関数を実行し、d_c = d_a + d_bを計算

5. データ転送:GPU → CPU

cudaMemcpy(&c, d_c, size, cudaMemcpyDeviceToHost);
  • cudaMemcpyDeviceToHost: GPUからCPUへ転送
  • 計算結果をcに取得

6. 結果の表示

printf("1 + 1 = %d\n", c);
  • 結果を表示(c = 2

7. GPUメモリの解放

cudaFree(d_a);
cudaFree(d_b);
cudaFree(d_c);
  • cudaFree: GPUメモリを解放

実行方法

Makefile

NVCC = nvcc
TARGET = add
SRC = src/add.cu
CFLAGS = -O2

$(TARGET): $(SRC)
	$(NVCC) $(CFLAGS) -o $(TARGET) $(SRC)

clean:
	rm -f $(TARGET)

.PHONY: clean

コンパイルと実行

make
./add

実行結果:

~/workspace/my/gpu_test[130] > ./add 
1 + 1 = 2

CUDAプログラミングの基本フロー

  1. CPU側で変数を初期化a=1, b=1
  2. GPUメモリを確保cudaMalloc
  3. CPU → GPU にデータを転送cudaMemcpy
  4. GPUで計算実行<<<>>>でカーネル起動)
  5. GPU → CPU に結果を転送cudaMemcpy
  6. 結果を表示
  7. GPUメモリを解放cudaFree

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?