GPUのアーキテクチャと プログラム構造

GPUのアーキテクチャと
プログラム構造
長岡技術科学大学
電気電子情報工学専攻
出川智啓
今回の内容

GPUのアーキテクチャ

CUDA

CUDAによるプログラミング
58
GPGPU実践プログラミング
2015/04/22
GPU(Graphics Processing Unit)とは

画像処理専用のハードウェア


具体的には画像処理用のチップ
チップ単体では販売されていない



59
PCI‐Exカードで販売(チップ単体と区別せずにGPUと呼ぶことも多い)
ノートPCに搭載
PCI‐Exカードとして販売されるGPUには,ビデオメモリと呼ばれ
るRAMが搭載
GPGPU実践プログラミング
2015/04/22
GPU(Graphics Processing Unit)の役割


グラフィックスを表示するために様々な処理を行い,処
理の結果をディスプレイに出力
3次元グラフィックスの発展に伴って役割が大きく変化
過去
現在
描画情報
CPU
3次元座標変換
ポリゴンとピクセルの
対応付け
描画情報

CPU が 3D 描 画
の演算を実行

GPUが出力
3次元座標変換
ポリゴンとピクセルの
対応付け
ピクセル色計算
テクスチャ参照
ピクセル色計算
テクスチャ参照
フレームバッファ(ビデ
オメモリ)への書き込み
フレームバッファ(ビデ
オメモリ)への書き込み
ディスプレイ出力
ディスプレイ出力
ディスプレイコントローラ
60
画面出力
GPGPU実践プログラミング
GPU


GPUが演算から
出力までの全て
を担当
CPUは描画情報
の生成やGPUへ
の情報の引き渡
し , GPU の 制 御
を行う
画面出力
2015/04/22
GPUの描画の流れ
1. CPUからGPUへ描画情報を送信
2. 頂点処理(頂点シェーダ)



2.
座標変換
画面上での頂点やポリゴンの位置・大きさの決定
頂点単位での照明の計算
3.
3. 頂点やポリゴンからピクセルを生成
(ラスタライザ)
4. ピクセル処理(ピクセルシェーダ)


画面上のピクセルの色
テクスチャの模様
4.
5. 画面出力

61
ピクセルの色情報をフレームバッファに書き込み
GPGPU実践プログラミング
2015/04/22
ビデオカードからGPUへ

CGの多様化と共に固定機能の実装が困難に

頂点処理とピクセル処理をユーザが書き換えられるプロ
グラマブルシェーダの実装
62
グラフィックスカード
GPU
頂点処理用回路
頂点シェーダユニット
ピクセル処理用回路
ピクセルシェーダユニット
GPGPU実践プログラミング
2015/04/22
レンダリングパイプライン処理
頂点情報
光源情報
視野変換
形状データの画面
への投影像
実数演算
陰影計算
材質情報
投影変換
クリッピング
投影像を画素
へ変換
整数演算とメモリ
アクセス
ビューポート変換
走査変換
合成
テクスチャ
出力画像
63
GPGPU実践プログラミング
2015/04/22
レンダリングパイプライン処理
頂点情報
光源情報
視野変換
形状データの画面
への投影像
実数演算
実数演算を行うハード
ウェアは高価だった
陰影計算
材質情報
投影変換
クリッピング
ビューポート変換
ハードウェアで処理
(固定機能)
走査変換
合成
テクスチャ
出力画像
64
GPGPU実践プログラミング
2015/04/22
レンダリングパイプライン処理
頂点情報
光源情報
視野変換
ハードウェアで処理
(固定機能)
陰影計算
材質情報
投影変換
クリッピング
ビューポート変換
ハードウェアで処理
(固定機能)
走査変換
合成
テクスチャ
出力画像
65
GPGPU実践プログラミング
2015/04/22
レンダリングパイプライン処理
頂点情報
視野変換
光源情報
頂点シェーダ
陰影計算
材質情報
投影変換
クリッピング
ビューポート変換
ピクセルシェーダ
走査変換
合成
テクスチャ
出力画像
66
GPGPU実践プログラミング
2015/04/22
ビデオカードからGPUへ

頂点処理とピクセル処理をユーザが書き換えられるプロ
グラマブルシェーダの実装

処理によっては利用効率に差が生じる
頂点処理重視の処理
ピクセル処理重視の処理
GPU
GPU
頂点シェーダユニット
頂点シェーダユニット
空きユニット
ピクセルシェーダユニット
ピクセルシェーダユニット
空きユニット
67
GPGPU実践プログラミング
2015/04/22
ビデオカードからGPUへ

頂点シェーダとピクセルシェーダを統合したユニファイド
シェーダへの進化

頂点処理とピクセル処理を切り替えることで利用率を高める
ピクセル処理重視の処理
頂点処理重視の処理
68
GPU
GPU
ユニファイドシェーダユニット
ユニファイドシェーダユニット
GPGPU実践プログラミング
2015/04/22
ビデオカードからGPUへ

各ピクセルに対して処理を並列に実行

単純な処理を行う演算器(Streaming Processor, SP)を大量に搭載


演算器は現在CUDA Coreという名称に変更
高い並列度で処理を行う
69
GPGPU実践プログラミング
2015/04/22
Teslaアーキテクチャの構造

Tesla C1060の仕様



70
SM数
30
CUDA Core数
240(=8 Core/SM×30 SM)
キャッシュを搭載せず
GPGPU実践プログラミング
2015/04/22
Teslaアーキテクチャの構造

Tesla C1060の仕様
CUDAコア数(単精度)
240 Cores
CUDAコアクロック周波数
1,296 MHz
単精度演算ピーク性能
622*1 (933*2) GFLOPS
倍精度演算ユニット数
30*3 Units
倍精度演算ピーク性能
78 GFLOPS
メモリクロック周波数
800 MHz
メモリバス幅
512 bit
最大メモリバンド幅*4
102 GB/s
*1単精度演算ピーク性能 = コアクロック周波数×コア数×命令の同時発行数(2)
*2CUDA CoreとSFUが同時に命令を発行できれば1296 MHz×240×3
*3一つのSMに倍精度演算器が一つ搭載
*4最大メモリバンド幅=メモリクロック周波数×メモリバス幅/8×2(Double Data Rate)
71
GPGPU実践プログラミング
2015/04/22
Fermiアーキテクチャの構造

Tesla M2050の仕様




72
SM数
14
CUDA Core数
448(=32 Core/SM×14 SM)
L1/L2 キャッシュを搭載
ECC(誤り訂正機能)を搭載
GPGPU実践プログラミング
2015/04/22
Fermiアーキテクチャの構造

Tesla M2050の仕様
CUDAコア数(単精度)
448 Cores
CUDAコアクロック周波数
1,150 MHz
単精度演算ピーク性能
1.03 TFLOPS
倍精度演算ユニット数
0*1 Unit
倍精度演算ピーク性能
515 GFLOPS
メモリクロック周波数
1.55 GHz
メモリバス幅
384 bit
最大メモリバンド幅
148 GB/s
*1単精度CUDA Coreを2基使って倍精度演算を実行
73
GPGPU実践プログラミング
2015/04/22
Keplerアーキテクチャの構造

Tesla K20c/mの仕様

SMX数


74
13
Streaming Multiprocessor eXtreme (?)
CUDA Core数
2,496(=192 Core/SM×13 SMX)
GPGPU実践プログラミング
2015/04/22
Keplerアーキテクチャの構造

Tesla K20c/mの仕様
CUDAコア数(単精度)
2,496 Cores
CUDAコアクロック周波数
706 MHz
単精度演算ピーク性能
3.52 TFLOPS
倍精度演算ユニット数
832*1 Units
倍精度演算ピーク性能
1.17 TFLOPS
メモリクロック周波数
2.6 GHz
メモリバス幅
320 bit
最大メモリバンド幅
208 GB/s
*164基/SMX×13基
75
GPGPU実践プログラミング
2015/04/22
Maxwellアーキテクチャ

GeForce GTX TITAN Xの仕様


76
SM数
CUDA Core数
24
3,072(=128 Core/SM×24 SM)
GPGPU実践プログラミング
2015/04/22
Maxwellアーキテクチャ
*http://ja.wikipedia.org/wiki/FLOPS
*
 GeForce GTX TITAN Xの仕様 http://http://www.geforce.com/hardware/desk
top‐gpus/geforce‐gtx‐titan‐x/specifications
CUDAコア数(単精度)
3,072 Cores
CUDAコアクロック周波数
1,002 MHz
単精度演算ピーク性能
6.14 TFLOPS
倍精度演算ユニット数
0*1 Units
倍精度演算ピーク性能
192 GFLOPS*2
メモリクロック周波数
3.5 GHz*3
メモリバス幅
384 bit
最大メモリバンド幅
336.5 GB/s
*1http://www.4gamer.net/games/121/G012181/20141225075/
*2倍精度演算は単精度演算の性能の1/32 (1/16 Flop/Core/clock)
*3DDR(Double Data Rate) 7GHz相当と書かれている場合もある
77
GPGPU実践プログラミング
2015/04/22
Pascalアーキテクチャ

2016年にリリース予定


NVLink




倍精度演算器を搭載予定
GPU同士やGPUとCPUを接続する独自の方式
通信(CPU ↔ メモリ ↔ PCI Express ↔ メモリ ↔ GPU)の
ボトルネックを解消(PCI Express3.0の5~12倍)
複数のGPUを使って大規模な計算が可能
3Dメモリ(High Bandwidth Memory, HBM)*


3次元積層技術を利用し,メモリの容量と帯域を大幅に増加
最大32GB,メモリ帯域1TB/s
*http://pc.watch.impress.co.jp/docs/column/kaigai/20150421_698806.html
78
GPGPU実践プログラミング
2015/04/22
Voltaアーキテクチャ

Pascalの後継
詳しい情報は不明

アメリカの次世代スーパーコンピュータへ採用予定





オークリッジ国立研究所
SUMMIT
ローレンス・リバモア研究所 SIERRA
150~300PFLOPS
100PFLOPS以上
地球シミュレータと同等の演算性能を1ノードで実現
現在Top500 2位のスーパーコンピュータと同じ電力で5~10
倍高速,サイズは1/5
*http://www.4gamer.net/games/121/G012181/20141225075/
79
GPGPU実践プログラミング
2015/04/22
GPUの模式図
GPU
Chip
SM
SM
Streaming
Multiprocessor
SM
SM
・・・
SM
・・・
SM
SM
SM
・・・
SM
SM
ローカル
メモリ
SM
L1キャッ
シュ
レジ
スタ
レジ
スタ
共有
メモリ
レジ
スタ
レジ
スタ
CUDA CUDA CUDA CUDA Core Core Core Core
・・・
SM
GPU
Streaming Streaming Multiprocessor
Multiprocessor
CUDA CUDA CUDA CUDA CUDA Core
CUDA Core
CUDA Core
CUDA Core
Core
Core
Core
Core
L2キャッシュ
コンスタントメモリ
テクスチャメモリ
ローカル
グローバルメモリ
メモリ
80
GPGPU実践プログラミング
2015/04/22
GPUの並列化の階層

グリッド-ブロック-スレッドの3階層

グリッド(Grid)



スレッド(Thread)



並列に実行する処理
GPUが処理を担当する領域全体
GPUの処理の基本単位
CPUのスレッドと同じ
ブロック(Block)もしくはスレッドブロック

81
スレッドの集まり
GPGPU実践プログラミング
2015/04/22
GPUの並列化の階層

GPUのハードウェアの構成に対応させて並列性を管理
ハードウェア構成
並列化の階層
CUDA
GPU
並列に実行する
処理
Grid
Streaming Multiprocessor
スレッドの集
まり
Block
スレッド
Thread
CUDA Core
82
GPGPU実践プログラミング
2015/04/22
CUDA

Compute Unified Device Architecture






NVIDIA社製GPU向け開発環境(Windows,Linux,Mac OS X)
2007年頃発表
C/C++言語+独自のGPU向け拡張
専用コンパイラ(nvcc)とランタイムライブラリ
いくつかの数値計算ライブラリ(線形代数計算,FFTなど)
CUDA登場以前

グラフィックスプログラミングを利用


83
足し算を行うために,色を混ぜる処理を実行
汎用計算のためには多大な労力が必要
GPGPU実践プログラミング
2015/04/22
CUDAによるプログラミング

CPUをホスト(Host),GPUをデバイス(Device)と表現

ホスト(CPU)

処理の流れやGPUを利用するための手続きを記述

プログラムの書き方は従来のC言語と同じ

利用するGPUの決定,GPUへのデータ転送,GPUで実行する関
数の呼び出し等
84
GPGPU実践プログラミング
2015/04/22
CUDAによるプログラミング

CPUをホスト(Host),GPUをデバイス(Device)と表現

デバイス(GPU)

処理する内容を関数として記述

引数は利用可能,返値は利用不可(常にvoid)

関数はkernelと呼ばれる

関数呼び出しはlaunch, invokeなどと呼ばれる
85
GPGPU実践プログラミング
2015/04/22
Hello World

何を確認するか



最小構成のプログラムの作り方
ファイル命名規則(拡張子は.c/.cpp)
コンパイルの方法(gcc, cl等を使用)
#include<stdio.h>
int main(void){
printf("hello world¥n");
return 0;
}
helloworld.c
86
GPGPU実践プログラミング
2015/04/22
CUDAでHello World

何を確認するか



最小構成のプログラムの作り方
ファイル命名規則(拡張子は.cu)
コンパイルの方法(nvccを使用)
#include<stdio.h>
#include<stdio.h>
int main(void){
int main(void){
printf("hello world¥n");
printf("hello world¥n");
違いは拡張子だけ?
return 0;
return 0;
}
}
helloworld.cu
87
GPGPU実践プログラミング
helloworld.c
2015/04/22
CUDAプログラムのコンパイル

ソースファイルの拡張子は.cu

nvccを用いてコンパイル


CPUが処理する箇所はgcc等がコンパイル

GPUで処理する箇所をnvccがコンパイル
helloworld.cuにはCPUで処理する箇所しかない
88
GPGPU実践プログラミング
2015/04/22
CUDAでHello World

CUDA専用の処理を追加
#include<stdio.h>
__global__ void kernel(){}
int main(void){
・・・ GPUで実行される関数(カーネル)
__global__が追加されている
kernel<<<1,1>>>();
printf("hello world¥n"); ・・・ 通常の関数呼出とは異なり,
<<<>>>が追加されている
return 0;
}
helloworld_kernel.cu
89
GPGPU実践プログラミング
2015/04/22
CUDAプログラムの実行

実行時の流れ(CPU視点)



利用するGPUの初期化やデータの転送などを実行
GPUで実行する関数を呼び出し
GPUから結果を取得
time
CPU
GPU
初期化の指示
必要なデータのコピー
カーネルの実行指示
CPUとGPUは非同期
CPUは別の処理を実行可能
結果の取得
90
初期化
メモリに書込
カーネルを実行
実行結果をコピー
GPGPU実践プログラミング
2015/04/22
GPUの構造とカーネルの書き方
プログラムからGPUで実行する関数を呼出
 GPUで実行する関数という目印が必要

GPUはPCI‐Exバスを経由してホストと接続
 GPUはホストと別に独立したメモリを持つ
 関数の実行に必要なデータはGPUのメモリに置く

GPUはマルチスレッド(メニースレッド)で並列処理
 関数には1スレッドが実行する処理を書く
 関数を実行する際に並列処理の度合いを指定

91
GPGPU実践プログラミング
2015/04/22
GPUの構造とカーネルの書き方
GPUで実行する関数(カーネル)という目印
 修飾子__global__を付ける

GPUはPCI‐Exバスを経由してホストと接続
 GPUはホストと別に独立したメモリを持つ
 カーネルの返値をvoidにする

GPUはマルチスレッド(メニースレッド)で並列処理
 カーネルには1スレッドが実行する処理を書く
 カーネル名と引数の間に<<<1,1>>>を付ける

92
GPGPU実践プログラミング
2015/04/22
Hello Thread(Fermi世代以降)

GPUの各スレッドが画面表示
#include<stdio.h>
__global__ void hello(){
printf("Hello Thread¥n"); ・・・ 画面表示(Fermi世代以降で可能)
コンパイル時にオプションが必要
}
‐arch=sm_20以降
int main(void){
hello<<<1,1>>>();
cudaThreadSynchronize();
return 0;
}
93
・・・ カーネル実行
・・・ ホストとデバイスの同期をとる
CPUとGPUは原則同期しないので,
同期しないとカーネルを実行した
直後にプログラムが終了
hellothread.cu
GPGPU実践プログラミング
2015/04/22
Hello Thread(Fermi世代以降)

<<< >>>内の数字で並列度が変わることの確認
#include<stdio.h>
__global__ void hello(){
printf("Hello Thread¥n");
}
int main(void){
hello<<<?,?>>>();
cudaThreadSynchronize();
return 0;
・・・ <<<>>>内の数字を変えると画面
表示される行数が変わる
<<<1,8>>>, <<<8,1>>>, <<<4,2>>>等
}
hellothread.cu
94
GPGPU実践プログラミング
2015/04/22
CPUとGPUのやりとり

GPUの想定される使い方



ホスト(CPU)からデータを送り,デバイス(GPU)で計算し,
結果を受け取る
CPUとGPUのデータのやり取りが必要
GPUは原則データを返さない


PCI‐Ex経由で描画情報を受け取り,画面に出力
カーネルの返値がvoidの理由
NVIDIA社ホームページより引用
95
GPGPU実践プログラミング
2015/04/22
CPUとGPUのやりとり

CUDA独自の命令とC言語のポインタを利用

GPUのメモリ上に計算に必要なサイズを確保

確保したメモリのアドレスをC言語のポインタで格納

ポインタの情報を基にデータを送受信
96
GPGPU実践プログラミング
2015/04/22
CPUとGPUのやり取り(単純な加算)

int型の変数2個を引数として受け取り,2個の和を返す

C言語らしい書き方
#include<stdio.h>
int add(int a, int b){
return a + b;
}
・・・ 引数で渡された変数の和を返す
int main(void){
int c;
c = add(6, 7);
printf("6 + 7 = %d¥n", c);
・・・ 関数呼び出し
return 0;
}
add_naive.c
97
GPGPU実践プログラミング
2015/04/22
CPUとGPUのやり取り(単純な加算)

関数の返値をvoidに変更し,メモリの動的確保を使用
#include<stdio.h>
#include<stdlib.h>
void add(int a, int b, int *c){
*c = a + b;
}
・・・ 引数で渡された変数の和を,cが指す
アドレスに書き込み
int main(void){
int c;
int *addr_c;
addr_c = (int *)malloc(sizeof(int));
add(6, 7, addr_c);
c = *addr_c;
printf("6 + 7 = %d¥n", c);
・・・ 引数にアドレスを追加
・・・ アドレスを基に結果を参照
return 0;
add.c
}
98
GPGPU実践プログラミング
2015/04/22
CPUプログラム(メモリの動的確保)

malloc


指定したバイト数分のメモリを確保
stdlib.hをインクルードする必要がある
#include<stdlib.h>
int *a;
a = (int *)malloc( sizeof(int)*100 );

sizeof

データ型1個のサイズ(バイト数)を求める
printf("%d, %d¥n", sizeof(float), sizeof(double));
実行すると4,8と表示される
99
GPGPU実践プログラミング
2015/04/22
CPUとGPUのやり取り(単純な加算)

add.cの処理の一部をGPUの処理に置き換え
#include<stdio.h>
__global__ void add(int a, int b, int *c){
*c = a + b;
}
・・・ __global__を追加
int main(void){
int c;
int *dev_c;
・・・ GPU上のメモリに確保される変数のアドレス
cudaMalloc( (void **)&dev_c, sizeof(int) ); ・・・ GPU上にint型変数
一個分のメモリを確保
add<<<1, 1>>>(6, 7, dev_c);
cudaMemcpy(&c, dev_c, sizeof(int), cudaMemcpyDeviceToHost);
printf("6 + 7 = %d¥n", c);
↑GPUから結果をコピー
cudaFree(dev_c);
・・・ メモリを解放
return 0;
add.cu
}
100
GPGPU実践プログラミング
2015/04/22
CUDAでカーネルを作成するときの制限

カーネルの引数





値を渡すことができる
GPUのメモリを指すアドレス
CPUのメモリを指すアドレスも渡すことは可能
そのアドレスを基にホスト側のメモリを参照することは不可能
printfなどの画面出力

Fermi世代以降のGPUで,コンパイルオプションを付与


エミュレーションモード

101
‐arch={sm_20|sm_21|sm_30|sm_32|sm_35|sm_50|sm_52}
新しいCUDA(4.0以降)では消滅
GPGPU実践プログラミング
2015/04/22
CPUプログラムの超簡単移植法

とりあえずGPUで実行すればいいのなら・・・

拡張子を.cuに変更

GPUの都合を反映



関数の返値をvoidにし,__global__を付ける
関数名と引数の間に<<<1,1>>>を付ける
GPUで使うメモリをcudaMallocで確保



カーネルの完成
mallocでメモリを確保していればそれをcudaMallocに置き換え
GPUからデータを受け取るためにcudaMemcpyを追加
最適化は追々考えればいい
102
GPGPU実践プログラミング
2015/04/22
Hello Thread(Fermi世代以降)


<<< >>>内の数字で並列度が変わる
この情報を利用すれば並列処理が可能
#include<stdio.h>
__global__ void hello(){
printf("Hello Thread¥n");
}
int main(void){
hello<<<?,?>>>();
cudaThreadSynchronize();
return 0;
・・・ <<<>>>内の数字を変えると画面表示
される行数が変わる
<<<1,8>>>, <<<8,1>>>, <<<4,2>>>等
}
hellothread.cu
103
GPGPU実践プログラミング
2015/04/22
GPUの並列化の階層


GPUのハードウェアの構成に対応させて並列性を管理
並列化の各階層における情報を利用
ハードウェア構成
並列化の階層
CUDA
GPU
並列に実行する
処理
Grid
Streaming Multiprocessor
スレッドの集
まり
Block
スレッド
Thread
CUDA Core
104
GPGPU実践プログラミング
2015/04/22
GPUの並列化の階層


グリッド-ブロック-スレッドの3階層
各階層の情報を参照できる変数


グリッド(Grid)


gridDim
グリッド内にあるブロックの数
ブロック(Block)



x,y,zをメンバにもつdim3型構造体
blockIdx
blockDim
ブロックに割り当てられた番号
ブロック内にあるスレッドの数
スレッド(Thread)

105
threadIdx
スレッドに割り当てられた番号
GPGPU実践プログラミング
2015/04/22
Hello Threads(Fermi世代以降)

<<< >>>内の数字で表示される内容が変化
#include<stdio.h>
__global__ void hello(){
printf("gridDim.x=%d, blockIdx.x=%d,
blockDim.x=%d, threadIdx.x=%d¥n",
gridDim.x, blockIdx.x, blockDim.x, threadIdx.x);
}
int main(void){
hello<<<?,?>>>();
cudaThreadSynchronize();
return 0;
・・・ <<<>>>内の数字を変えると画面表示
される内容が変わる
<<<>>>内の数字とどのパラメータが
対応しているかを確認
}
hellothreads.cu
106
GPGPU実践プログラミング
2015/04/22
GPUの構造とカーネルの書き方
GPUはマルチスレッド(メニースレッド)で並列処理
 関数には1スレッドが実行する処理を書く
 関数を実行する際に並列処理の度合いを指定


カーネルと引数の間に追加した<<<,>>>で並列処理の
度合を指定

107
<<<グリッド内にあるブロックの数,1ブロックあたりのスレッド
の数>>>
GPGPU実践プログラミング
2015/04/22
プログラム実習

以下のプログラムをコンパイルし,正しく実行できること
を確認せよ





helloworld.c
helloworld.cu
hellothread.cu
hellothreads.cu
hellothreads.cuについては,<<<>>>内の数字を変
更し,実行結果がどのように変わるか確認せよ
108
GPGPU実践プログラミング
2015/04/22
レポート課題1(提出期限は1学期末)

二つの値を交換する関数swapをGPUに移植せよ
並列化する必要はなく,1スレッドで実行すればよい

#include<stdio.h>
void swap(int *addr_a, int *addr_b){
int c; //cは値を一時的に保持するための変数
c = *addr_a; //*は間接参照演算子
*addr_a = *addr_b; //メモリアドレス(=addr_a,addr_bの値)にある変数の値を参照
*addr_b = c;
}
int main(void){
int a=1,b=2;
printf("a = %d, b = %d¥n", a, b);
swap(&a, &b); //変数a, bのメモリアドレスを渡す.&はアドレス演算子
printf("a = %d, b = %d¥n", a, b);
return 0;
}
swap.c
109
GPGPU実践プログラミング
2015/04/22
レポート課題1(提出期限は1学期末)
#include<stdio.h>
カーネルという目印 void swap(int *a, int *b){
?
}
int main(void){
int a=1,b=2;
GPUで使う変数を宣言
printf("a = %d, b = %d¥n", a, b);
GPU上のメモリを確保(aの分)
GPU上のメモリを確保(bの分)
CPUからGPUにメモリの内容をコピー(aの分)
CPUからGPUにメモリの内容をコピー(bの分)
swap実行時の並列度の指定(GPUで使う変数, GPUで使う変数);
GPUのメモリの内容をCPUにコピー(aの分)
GPUのメモリの内容をCPUにコピー(bの分)
printf("a = %d, b = %d¥n", a, b);
return 0;
}
110
GPGPU実践プログラミング
2015/04/22