SlideShare a Scribd company logo
第13回 GPUのメモリ階層
長岡技術科学大学 電気電子情報工学専攻 出川智啓
今回の内容
GPGPU実践基礎工学
 GPUのメモリ階層
 グローバルメモリ
 共有メモリ
 モザイク処理への適用
 コンスタントメモリ
 空間フィルタへの適用
2 2015/12/02
GPUの主要部品
GPGPU実践基礎工学
 基盤
 画面出力端子
 電源入力端子
 GPU(チップ)+冷却部品
 メモリ
 特性の把握が重要
http://www.geforce.com/whats‐new/articles /introducing‐the‐geforce‐gtx‐780
に公開されている写真を基に作成
画面出力端子
PCI‐Ex端子
電源入力端子
メモリ
チップ
3 2015/12/02
CPUのメモリ階層
GPGPU実践基礎工学
 オフチップ(off‐chip)メモリ
 CPUのチップ外部に置かれたメモリ
 メインメモリ(主記憶)
 利用可能なメモリの中で最低速,最大容量
 オンチップ(on‐chip)メモリ
 CPUのチップ内部に置かれたメモリ
 レジスタ
 レベル1(L1)キャッシュ
 レベル2(L2)キャッシュ
 レベル2(L3)キャッシュ
4
高速,容量小
低速,容量大
2015/12/02
GPUのメモリ階層
GPGPU実践基礎工学
 オフチップメモリ
 PCI‐Exカードの基板上に実装
 ビデオメモリ
 利用可能なメモリの中で最低速,最大容量
 オンチップメモリ
 GPUのチップ内部に置かれたメモリ
 レジスタ
 レベル1(L1)キャッシュ
 レベル2(L2)キャッシュ
CPUの構造に類似
5
高速,容量小
低速,容量大
2015/12/02
GPUメモリの独自の特徴
GPGPU実践基礎工学
 CPUとは異なるメモリを複数搭載
 各メモリの特徴を知り,適材適所で利用する事により高速化
 GPUから読み書き可能か
 処理を行うスレッドから読み書き可能か,読み込みのみか
 複数のスレッドでデータを共有できるか
 CPUから読み書き可能か
 C言語の機能のみで直接読み書きは不可能
 CUDAの専用関数(API)を利用して読み書き
6 2015/12/02
メモリの階層
GPGPU実践基礎工学
 CPUのメモリ階層
 コアごとにL2キャッシュ,全体でL3キャッシュを持つこともある
メインメモリ
L2キャッシュ
・・・
・・・
チップ
7
コア
L1キャッシュ
演算器
レジスタ レジスタ
演算器
L1キャッシュ
演算器
レジスタ レジスタ
演算器
L1キャッシュ
演算器
レジスタ レジスタ
演算器
コア コア
2015/12/02
メモリの階層
GPGPU実践基礎工学
 GPUのメモリ階層
 CPUにはない独自のメモリを複数持つ
グローバルメモリ
L2キャッシュ
L1キャッシュ 共有メモリ
CUDA Core
レジスタ
チップ
テクスチャ
メモリ
コンスタント
メモリ
ローカル
メモリ
テクスチャ
キャッシュ
コンスタント
キャッシュ
8 2015/12/02
メモリの種類
 オンチップメモリ(GPUのチップ内部に置かれたメモリ)
 高速アクセス,小容量
 CPUからはアクセス不可
 L1キャッシュと共有メモリは一定サイズを共用
GPGPU実践基礎工学9
L1キャッシュ/共有(シェアー
ド)メモリ
レジスタ
容量 小 小
速度 高速 高速
GPUからの
読み書き
読み書き可
ブロック内の全スレッドが同じメモリに
アクセス(データを共有する)ことが可
能*
読み書き可
各スレッドが異なるアドレス
にアクセス
CPUからの
アクセス
読み書き不可 読み書き不可
2015/12/02
*同じメモリ,異
なるメモリにつ
いては後ろの
スライドで説明
メモリの種類
 オフチップメモリ(GPUのチップ外部に置かれたメモリ)
 低速アクセス,大容量
 CPUから直接アクセス可能
 ローカルメモリだけはアクセス不可
GPGPU実践基礎工学10
グローバルメモリ ローカルメモリ テクスチャメモリ コンスタントメモリ
容量 大 小 大 小
速度 低速 低速 高速* 高速*
GPUからの
読み書き
読み書き可
全てのスレッドが同じ
メモリにアクセス可能*2
読み書き可
各スレッドが異なるメ
モリにアクセス*2
読み込み可
全てのスレッドが同じ
メモリにアクセス可能*2
読み込み可
全てのスレッドが同じ
メモリにアクセス*2
CPUからの
アクセス
読み書き可 読み書き不可 読み書き可 読み書き可
2015/12/02
*1キャッシュが効く場合
*2同じメモリ,異なるメモリについては後ろのスライドで説明
同じメモリ
2015/12/02GPGPU実践基礎工学11
 複数のスレッドがメモリアドレスを共有
 複数のスレッドが変数を共有
 他のスレッドが書き込んだデータを読むことが可能
 共有できるスレッドの範囲はメモリの種類によって変化
//a,b[]がグローバルメモリに確保されている場合*1
__global__ void kernel(...){
int i = blockIdx.x*blockDim.x + threadIdx.x;
:
b[i] = i; //スレッドiが配列bのi番目に自身のスレッド番号を代入
//b[0,1,...,i‐1,i,...]の値は0,1,...,i‐1,i,...
a = b[i‐1];*2 //スレッドi‐1が書き込んだ値を読み*3,aに代入
:         //最後に書き込まれたaの値を全スレッドが共有
} *1 あくまで動作のイメージを説明するための例で正しく実行できない
*2 iが0の場合は考えない
*3 配列bを全スレッドが共有しているので,書き込んだ値以外を読む事が可能
異なるメモリ
2015/12/02GPGPU実践基礎工学12
 メモリアドレスが共有できず,一つのスレッドのみがその
メモリアドレスにアクセス
 あるスレッドが宣言した変数へアクセスできない
//a,b[]がレジスタに確保されている場合*1
__global__ void kernel(...){
int i = blockIdx.x*blockDim.x + threadIdx.x;
:
b[i] = i; //スレッドiが配列bのi番目に自身のスレッド番号を代入
//b[0,1,...,i‐1,i,...]の値はb[i]以外不定
a = b[i‐1];*2 //b[i‐1]の値(不定)をaに代入*3
:         //aの値はスレッドによって異なる
} *1 あくまで動作のイメージを説明するための例で正しく実行できない
*2 iが0の場合は考えない
*3 配列bは他のスレッドからアクセスできないため,代入した値以外は不定のまま
 Tesla世代
 L1,L2キャッシュなし
 テクスチャキャッシュ,コンスタ
ントキャッシュは利用可能
 高速なメモリの活用が重要
 共有メモリ
 レジスタ
メモリの種類
2015/12/02GPGPU実践基礎工学13
オフチップメモリ
オンチップメモリ
ホスト
メモリ
コンスタントメモリ
テクスチャメモリ
GPU
Chip
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
共有メモリ
SM
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
共有メモリ
SM
グローバルメモリ ローカル
メモリ
ローカル
メモリ ・・・
 Fermi世代以降
 共有メモリとL1キャッシュが
一体で利用可能
 グローバルメモリへのアクセ
スはL2キャッシュ経由
 Fermi世代では標準でL1
キャッシュも有効化*
メモリの種類
2015/12/02GPGPU実践基礎工学14
オフチップメモリ
オンチップメモリ
ホスト
メモリ
L2キャッシュ
コンスタントメモリ
テクスチャメモリ
GPU
Chip
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
L1キャッ
シュ
共有
メモリ
SM
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
L1キャッ
シュ
共有
メモリ
SM
グローバルメモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
・・・
・・・
*Kepler世代では標準でL1キャッシュが無効化
メモリの種類と並列化階層の対応
 オンチップメモリ
 ブロックまたはスレッドごとに
異なる値を持つ
 ローカルメモリはレジスタが
不足した時に使われる
 オフチップメモリ
 GPU全体で共通の値を持つ
2015/12/02GPGPU実践基礎工学15
各GPU(Grid)内
でデータを共有
各ブロック内で
データを共有
各スレッドが個別の
データを保有
L2キャッシュ
コンスタントメモリ
テクスチャメモリ
Grid
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
Thre
ad 0
Thre
ad 1
Thre
ad 2
Thre
ad 3
L1キャッ
シュ
共有
メモリ
Block(0,0,0)
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
Thre
ad 0
Thre
ad 1
Thre
ad 2
Thre
ad 3
L1キャッ
シュ
共有
メモリ
Block(1,0,0)
グローバルメモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
・・・
・・・
ホスト
メモリ
レジスタ
 各スレッドが個別に利用
 カーネル内で変数を宣言する
とレジスタを利用
 非常に高速
 キャッシュとしても利用可能
2015/12/02GPGPU実践基礎工学16
*Keplerからは65536本
 少容量
 32768本*×32bit
 利用可能分を超え
るとローカルメモリ
へ追い出される
 レジスタスピル
L2キャッシュ
コンスタントメモリ
テクスチャメモリ
GPU
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
L1キャッ
シュ
共有
メモリ
SM
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
L1キャッ
シュ
共有
メモリ
SM
グローバルメモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
・・・
・・・
Chip
ホスト
メモリ
L2キャッシュ
コンスタントメモリ
テクスチャメモリ
GPU
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
L1キャッ
シュ
共有
メモリ
SM
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
L1キャッ
シュ
共有
メモリ
SM
グローバルメモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
・・・
・・・
グローバルメモリ
 ビデオメモリ(数GB)
 CPUのメインメモリに相当
 読み込みがある一定サイズ
でまとめて行われる
 レイテンシが大きい
 効率よくアクセスするための
条件がある
 コアレスアクセス
 アラインアクセス
2015/12/02GPGPU実践基礎工学17
Tesla世代ではコアレスアクセスの条件に
メモリのアラインが含まれている
Chip
ホスト
メモリ
グローバルメモリへのアクセス
(Tesla世代)
 16スレッドが協調して同時にアクセス
 1 Warp = 32スレッド
 Warpの半分(Half Warp,16スレッド)が協調して処理を実行
 コアレスアクセスか否かで読み込みの速度が変化
 新しい世代のGPUでは,コアレスアクセスになる条件やコアレ
スアクセスできないときの速度の落ち込みが緩和
 コアレスアクセスはGPUのプログラムで最重要
 GPUの処理能力と比較するとデータ供給が不足しがち
 極力データ供給不足が生じないようプログラムを作成
2015/12/02GPGPU実践基礎工学18
コアレスアクセスになる条件
(Tesla世代)
 データのサイズ
 32bit, 64bit, 128bit(4byte, 8byte, 16byte)
 アドレスの隣接
 16スレッドがアクセスするアドレスがスレッド番号順に隣接
 スレッド番号順にデータサイズ分ずつアドレスが増加
 アクセスする最初のアドレス
 16スレッドがアクセスするアドレスの先頭が,64byteまたは
128byteの倍数
2015/12/02GPGPU実践基礎工学19
コアレスアクセスの例*
(Tesla世代)
 データ型が
32bit=4byte
 各スレッドが連
続して隣接アド
レスにアクセス
 先頭アドレス
が128バイト
境界
16スレッド
 データ型が
32bit=4byte
 各スレッドが連
続して隣接アド
レスにアクセス
 実際にデータ
を取得するか
は無関係
 先頭アドレス
が128バイト
境界
T15
T14
T13
T12
T11
T10
T9
T8
T7
T6
T5
T4
T3
T2
A188
A184
A180
A176
A172
A168
A164
A160
A156
A152
A148
A144
A140
A136
T1 A132
T0 A128
T15
T14
T13
T12
T11
T10
T9
T8
T7
T6
T5
T4
T3
T2
A188
A184
A180
A176
A172
A168
A164
A160
A156
A152
A148
A144
A140
A136
T1 A132
T0 A128
2015/12/02GPGPU実践基礎工学20
*CUDA Programming Guide
メモリアドレスに対する
スレッドのアクセス要求
T15
T14
T13
T12
T11
T10
T9
T8
T7
T6
T5
T4
T3
T2
A188
A184
A180
A176
A172
A168
A164
A160
A156
A152
A148
A144
A140
A136
T1 A132
T0 A128
T15
T14
T13
T12
T11
T10
T9
T8
T7
T6
T5
T4
T3
T2
A188
A184
A180
A176
A172
A168
A164
A160
A156
A152
A148
A144
A140
A136
T1 A132
T0 A128
T15
T14
T13
T12
T11
T10
T9
T8
T7
T6
T5
T4
T3
T2
A188
A184
A180
A176
A172
A168
A164
A160
A156
A152
A148
A144
A140
A136
T1 A132
T0 A128
T15
T14
T13
T12
T11
T10
T9
T8
T7
T6
T5
T4
T3
T2
A188
A184
A180
A176
A172
A168
A164
A160
A156
A152
A148
A144
A140
A136
T1 A132
T0 A128
コアレスアクセスにならない例
(Tesla世代)
2015/12/02GPGPU実践基礎工学21
・・・
各スレッドが番
号順にアクセス
していない
先頭が128バイト
境界ではない
アドレスが連続し
ていない
データが32bit, 
64bit, 128bit
ではない
コアレスアクセスにならない例
(Tesla世代)
2015/12/02GPGPU実践基礎工学22
 128バイト境界からわずか
にずれている場合
 Tesla世代以降は64バイト
ブロックと32バイトブロック
に分けて読込
 メモリアクセス要求は2回
 コアレスアクセスの半分程
度の性能は得られる
A190
64バイトブロック
でデータ読込
32バイトブロック
でデータ読込
T15
T14
T13
T12
T11
T10
T9
T8
T7
T6
T5
T4
T3
T2
A188
A184
A180
A176
A172
A168
A164
A160
A156
A152
A148
A144
A140
A136
T1 A132
T0 A128
グローバルメモリへのアクセス
(Fermi世代)
2015/12/02GPGPU実践基礎工学23
 Tesla世代のGPU
 グローバルメモリへのアクセスに強い制約があった
 以前のGPUよりは改善
 Fermi世代以降のGPU
 Tesla世代のGPUから大幅に改善
 効率のよいアクセスの条件
 コアレスアクセス+アラインアクセス
 L1キャッシュの利用状況によっても変化
グローバルメモリからの読込
(Fermi世代)
2015/12/02GPGPU実践基礎工学24
 メモリ操作の命令はWarpごとに発行
 1 Warp内の32スレッドが協調
 各スレッドのメモリアクセス要求を一つに集約
 メモリアクセス要求の処理
 128バイトもしくは32バイト単位
 すべてL2キャッシュを通過
 アーキテクチャによってはL1キャッシュも通過
 L1キャッシュの使用はコンパイルオプションで設定可能
 Fermi世代は標準でL1キャッシュが有効化
 Kepler世代は標準でL1キャッシュが無効化
グローバルメモリからの読込
(Fermi世代)
2015/12/02GPGPU実践基礎工学25
 コアレスメモリアクセス(coalesce access)
 メモリアドレスの連続性に着目
 1 Warp内の32スレッドが隣り合ったメモリにアクセス
 データサイズが4バイトの時,スレッド1がアクセスするメモリアドレス
はスレッド0がアクセスするメモリアドレス+4
 アラインメモリアクセス(align access)
 メモリの配置に着目
 Warpがアクセスするデータの先頭アドレスがキャッシュ粒度
の倍数
 L2キャッシュのみを使う場合は32バイトの倍数
 L1キャッシュも使う場合は128バイトの倍数
メモリ読込の例
2015/12/02GPGPU実践基礎工学26
 アライン/コアレスアクセス
 ミスアライン/コアレスアクセス
0 1
6
3
2
4
8
6
4
8
0
9
6
1
1
2
1
2
8
1
4
4
1
6
0
1
7
6
1
9
2
2
0
8
2
2
4
2
4
0
2
5
6
2
7
2
2
8
8
3
0
4
3
2
0
3
3
6
3
5
2
3
5
8
0 1 2 3 4 5 6 7 8 9 1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
0 1
6
3
2
4
8
6
4
8
0
9
6
1
1
2
1
2
8
1
4
4
1
6
0
1
7
6
1
9
2
2
0
8
2
2
4
2
4
0
2
5
6
2
7
2
2
8
8
3
0
4
3
2
0
3
3
6
3
5
2
3
5
8
0 1 2 3 4 5 6 7 8 9 1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
メモリアドレスに対する
スレッドのアクセス要求
Warp内でのスレッドID
(カーネル内でのスレッド番号とは異なる)
メモリアドレス
メモリ読込の例
2015/12/02GPGPU実践基礎工学27
 アライン/アンコアレスアクセス
 ミスアライン/アンコアレスアクセス
0 1
6
3
2
4
8
6
4
8
0
9
6
1
1
2
1
2
8
1
4
4
1
6
0
1
7
6
1
9
2
2
0
8
2
2
4
2
4
0
2
5
6
2
7
2
2
8
8
3
0
4
3
2
0
3
3
6
3
5
2
3
5
8
0 1 2 3 4 5 6 7 8 9 1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
0 1
6
3
2
4
8
6
4
8
0
9
6
1
1
2
1
2
8
1
4
4
1
6
0
1
7
6
1
9
2
2
0
8
2
2
4
2
4
0
2
5
6
2
7
2
2
8
8
3
0
4
3
2
0
3
3
6
3
5
2
3
5
8
0 1 2 3 4 56 7 8 9 1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
0 1
6
3
2
4
8
6
4
8
0
9
6
1
1
2
1
2
8
1
4
4
1
6
0
1
7
6
1
9
2
2
0
8
2
2
4
2
4
0
2
5
6
2
7
2
2
8
8
3
0
4
3
2
0
3
3
6
3
5
2
3
5
8
0 1 2 3 4 56 7 8 9 1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
メモリアドレスに対する
スレッドのアクセス要求
Fermi世代の標準的な読込
2015/12/02GPGPU実践基礎工学28
 L1キャッシュとL2キャッシュを通過
 読込は128バイト単位で実行
 L1キャッシュのキャッシュラインのサイズで実行
 読込の評価に利用する用語
 メモリトランザクション
 メモリのアクセス要求に対して排他的にメモリにアクセスして行う処理
の単位
 バスの利用率
 必要なデータサイズ/読込完了に必要な読込データサイズ
 アライン/コアレスアクセス
 Warp内の全スレッドが要求するメモリアドレスが128バイトの範
囲内
 全スレッドが隣り合ったメモリにアクセス
 先頭データのメモリアドレスが128バイトの倍数
 読込に必要な128バイトのトランザクションは一つ
 読み込んだデータ全てを利用
 バスの利用率は128/128=100%
0 1
6
3
2
4
8
6
4
8
0
9
6
1
1
2
読込の例
2015/12/02GPGPU実践基礎工学29
1
2
8
1
4
4
1
6
0
1
7
6
1
9
2
2
0
8
2
2
4
2
4
0
0 1 2 3 4 5 6 7 8 9 1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
2
5
6
2
7
2
2
8
8
3
0
4
3
2
0
3
3
6
3
5
2
3
5
8
Warp内でのスレッドID
(カーネル内でのスレッド番号とは異なる)
メモリアドレス
メモリアドレスに対するスレッドのアクセス要求
読込に必要な128バイトトランザクション
128バイトのキャッシュライン
読み込むデータ
読込の例
2015/12/02GPGPU実践基礎工学30
 アライン/アンコアレスアクセス
 Warp内の全スレッドが要求するメモリアドレスが128バイトの
範囲内(一つのキャッシュラインに収まる)
 各スレッドがアクセスするメモリアドレスが不連続
 先頭データのメモリアドレスが128バイトの倍数
 読込に必要な128バイトのトランザクションは一つ
 読み込んだデータ全てを利用
 バスの利用率は128/128=100%
0 1
6
3
2
4
8
6
4
8
0
9
6
1
1
2
0 1 2 3 4 5 6 7 8 9 1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
1
2
8
1
4
4
1
6
0
1
7
6
1
9
2
2
0
8
2
2
4
2
4
0
2
5
6
2
7
2
2
8
8
3
0
4
3
2
0
3
3
6
3
5
2
3
5
8
読込の例
2015/12/02GPGPU実践基礎工学31
 ミスアライン/コアレスアクセス
 Warpがアクセスするデータの先頭アドレスが128の倍数では
ない(一つのキャッシュラインに収まらない)
 全スレッドが隣り合ったメモリにアクセス
 先頭データのメモリアドレスが128バイトの倍数ではない
 読込に必要な128バイトのトランザクションは二つ
 読み込んだデータの半分だけを利用
 バスの利用率は128/(128×2)=50%
0 1 2 3 4 5 6 7 8 9 1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
0 1
6
3
2
4
8
6
4
8
0
9
6
1
1
2
1
2
8
1
4
4
1
6
0
1
7
6
1
9
2
2
0
8
2
2
4
2
4
0
2
5
6
2
7
2
2
8
8
3
0
4
3
2
0
3
3
6
3
5
2
3
5
8
読込の例
2015/12/02GPGPU実践基礎工学32
 ミスアライン/アンコアレスアクセス
 Warp内の全スレッドが同じアドレスにアクセス要求
 一つのキャッシュラインに収まる
 読込に必要な128バイトのトランザクションは一つ
 読み込んだ128バイトのうち利用されるのは4バイトのみ
 バスの利用率は4/128=3.125%
0 1 2 3 4 56 7 8 9 1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
0 1
6
3
2
4
8
6
4
8
0
9
6
1
1
2
1
2
8
1
4
4
1
6
0
1
7
6
1
9
2
2
0
8
2
2
4
2
4
0
2
5
6
2
7
2
2
8
8
3
0
4
3
2
0
3
3
6
3
5
2
3
5
8
読込の例
2015/12/02GPGPU実践基礎工学33
 ミスアライン/アンコアレスアクセス
 Warp内の各スレッドが広範囲に点在するデータにアクセス
 複数のキャッシュラインにまたがる(上の例では3個)
 読込に必要な128バイトのトランザクションは最悪で32個
 読み込んだデータのうち128バイトのみを利用
 バスの利用率は最悪で128/(128×32)=3.125%
 上の例では128/(128×3)=33.3%
 何度も読み込むための待ちが発生
0 1 2 3 4 56 7 8 9 1
0
1
1
1
2
1
3
1
4
1
5
1
6
1
7
1
8
1
9
2
0
2
1
2
2
2
3
2
4
2
5
2
6
2
7
2
8
2
9
3
0
3
1
0 1
6
3
2
4
8
6
4
8
0
9
6
1
1
2
1
2
8
1
4
4
1
6
0
1
7
6
1
9
2
2
0
8
2
2
4
2
4
0
2
5
6
2
7
2
2
8
8
3
0
4
3
2
0
3
3
6
3
5
2
3
5
8
モザイク処理
2015/12/02GPGPU実践基礎工学34
 前回授業で取り上げたモザイク処理
 画像を小さな領域に分け,その領域を全て同じ色にする
 領域内の全画素を,領域内の画素の平均値に置き換える
原画像 処理画像
モザイク処理
GPGPU実践基礎工学35
 前回授業で取り上げたモザイク処理
 高速化が今ひとつ
 他の処理より一桁遅い
処理
処理時間[ms]
CPU GPU
ネガティブ処理 175 1.17
水平反転 187 1.18
垂直反転 185 1.18
空間フィルタ 553 4.13
モザイク処理 260 38.5
2015/12/02
__global__ void mosaic(unsigned char *p, unsigned char *filtered, int mosaicSize){
int i,j, isub,jsub;
int average;
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
if(threadIdx.x == 0 && threadIdx.y == 0){//ブロック内の1スレッドのみが処理
//領域内の画素の平均値を計算
average = 0;
for(jsub = 0; jsub<mosaicSize; jsub++){
for(isub = 0; isub<mosaicSize; isub++){
average += p[(i+isub) + WIDTH*(j+jsub)];
}
}
average /= (mosaicSize*mosaicSize);
//領域内の画素を計算した平均値で塗りつぶす
for(jsub = 0; jsub<mosaicSize; jsub++){
for(isub = 0; isub<mosaicSize; isub++){
filtered[(i+isub) + WIDTH*(j+jsub)] = (unsigned char)average;
}
}
}
}
モザイク処理(前回授業で作成)
GPGPU実践基礎工学36 2015/12/02
imageproc.cu
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
if(threadIdx.x == 0 && threadIdx.y == 0){//1スレッドのみが処理
//領域内の画素の平均値を計算
//計算した平均値をグローバルメモリへ書き込む
}
モザイク処理(前回授業で作成)
2015/12/02GPGPU実践基礎工学37
 ブロックに分割し,ブロック内の1ス
レッドのみが動作
 ブロックの数だけ並列に処理
 ブロックの中では1スレッドのみが処理
 グローバルメモリから画素情報を読込
 ブロック内の画素の平均値を計算
 グローバルメモリに画素の平均値を書込
 残りのスレッドはi,jの計算をするだけ
p[]
モザイク処理が高速化されない原因
GPGPU実践基礎工学38
 各ブロックの1スレッドのみが処理を実行
 グローバルメモリから画素情報を読込
 ブロック内の画素の平均値を計算
 グローバルメモリに画素の平均値を書込
 グローバルメモリにアライン/コアレスアクセスできていない
 複数のスレッドが協調し,アドレスが隣接したメモリを読むと高速
 ある1スレッドが1画素ずつメモリアドレスを変えながら読むのは
最悪の処理
2015/12/02
モザイク処理が高速化されない原因
GPGPU実践基礎工学39
 せめてアライン/コアレスアクセスしたい
 平均を並列に計算するのは中級レベルの処理
 カーネル内で変数を宣言するとレジスタが使われる
 下の例ではaverageとcacheはレジスタに確保
 ブロック内で値を共有できない
__global__ void mosaic(unsigned char *p, unsigned char *filtered, int mosaicSize){
int i,j, isub,jsub;
int cache, average; //cacheとaverageはレジスタに確保(各スレッドが異なる値を保持)
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
cache = p[(i+isub) + WIDTH*(j+jsub)];//グローバルメモリから読み込み(コアレスアクセス)
if(threadIdx.x == 0 && threadIdx.y == 0){
//領域内の画素の平均値を計算したいが,他のスレッドが持つcacheの値を読む事は不可能
}
//グローバルメモリに書き出し(コアレスアクセス)
filtered[(i+isub) + WIDTH*(j+jsub)] = (unsigned char)average;
}
2015/12/02
メモリの種類
 オンチップメモリ(GPUのチップ内部に置かれたメモリ)
 高速アクセス,小容量
 CPUからはアクセス不可
 L1キャッシュと共有メモリは一定サイズを共用
GPGPU実践基礎工学40
L1キャッシュ/共有(シェアー
ド)メモリ
レジスタ
容量 小 小
速度 高速 高速
GPUからの
読み書き
読み書き可
ブロック内の全スレッドが同じメモリア
ドレスにアクセス(データを共有する)
ことが可能*
読み書き可
各スレッドが異なるレジスタ
にアクセス
CPUからの
アクセス
読み書き不可 読み書き不可
*スレッドごとに
異なるアドレス
にアクセスする
ことも可能
2015/12/02
L2キャッシュ
コンスタントメモリ
テクスチャメモリ
GPU
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
L1キャッ
シュ
共有
メモリ
SM
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
L1キャッ
シュ
共有
メモリ
SM
グローバルメモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
・・・
・・・
Chip
共有(シェアード)メモリ
 ブロック内のスレッドが共通
のデータ(メモリアドレス)に
アクセス可能
 物理的にSMに近い
 遅延はグローバルメモリの
20~30分の1,帯域幅は10倍
2015/12/02GPGPU実践基礎工学41
 Fermi世代以前のGPUで
マネージドキャッシュとして
利用
 1ブロックあたり
16,32*,48kB
*Kepler世代から
ホスト
メモリ
共有(シェアード)メモリの宣言
 修飾子 __shared__ を付けて宣言
 配列として宣言
 要素数を静的(コンパイル時)に決定する場合
 __shared__ 型 変数名[要素数]
 多次元配列も宣言可能(1,2,3次元)
 要素数を動的(カーネル実行時)に決定する場合
 extern __shared__ 型 変数名[]
 メモリサイズをカーネル呼出時のパラメータで指定
 <<<ブロック数,スレッド数,共有メモリのサイズ>>>
GPGPU実践基礎工学42 2015/12/02
=要素数*sizeof(共有メモリの型)
共有メモリを使ったモザイク処理の高速化
GPGPU実践基礎工学43
 ブロック内の全スレッドで共有したい値
 各スレッドがグローバルメモリから読んだ画素情報
 ブロック内の画素の平均値
 処理の流れ
1.ブロック内の全スレッドがグローバルメモリから画素の値を読
み出し,共有メモリに置く(コアレスアクセス)
2.ある1スレッドが共有メモリに置かれた画素の値を読み,画素
の平均値を計算し,共有メモリに置く
3.ブロック内の全スレッドが共有メモリに置かれた画素の平均
値を読み,グローバルメモリに書き込む(コアレスアクセス)
2015/12/02
__global__ void mosaic_shared(unsigned char *p,unsigned char *filtered, int mosaicSize){
int i,j, isub,jsub;
__shared__ int average;
__shared__ unsigned char cache[THREADX][THREADY];
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
cache[threadIdx.x][threadIdx.y] = p[i + WIDTH*j];
if(threadIdx.x == 0 && threadIdx.y == 0){
average = 0;
for(isub = 0; isub<mosaicSize; isub++){
for(jsub = 0; jsub<mosaicSize; jsub++){
average += cache[isub][jsub];
}
}
average /= (mosaicSize*mosaicSize);
}
filtered[i + WIDTH*j] = (unsigned char)average;
}
モザイク処理(共有メモリを利用)
GPGPU実践基礎工学44 2015/12/02
__shared__ int average;
__shared__ unsigned char cache[THREADX][THREADY];
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
cache[threadIdx.x][threadIdx.y] = p[i + WIDTH*j];
共有メモリの宣言と利用
2015/12/02GPGPU実践基礎工学46
 ブロック内のスレッド数
分の共有メモリを確保
 画素情報を共有するのは1
ブロックの中だけ
 配列サイズはブロック内の
スレッド数分でよい
 各スレッドがグローバル
メモリからデータを読み,
共有メモリに書込む
p[]
cache[][]
if(threadIdx.x == 0 && threadIdx.y == 0){
average = 0;
for(isub = 0; isub<mosaicSize; isub++){
for(jsub = 0; jsub<mosaicSize; jsub++){
average += cache[isub][jsub];
}
}
average /= (mosaicSize*mosaicSize);
}
共有メモリの宣言と利用
2015/12/02GPGPU実践基礎工学48
 1スレッドが共有メモリに置かれた画素
の値を読み,画素の平均値を計算
 画素の平均値averageも共有メモリに
存在
 ブロック内の全スレッドがaverageにアクセ
ス可能
cache[][] average
filtered[i + WIDTH*j] = (unsigned char)average;
共有メモリの宣言と利用
2015/12/02GPGPU実践基礎工学50
 各スレッドがaverageを
読み込み
 グローバルメモリの各位
置に画素の平均値を書
き込む
filtered[]
average
filtered[i + WIDTH*j] = (unsigned char)average;
実行結果
GPGPU実践基礎工学51
 正しく処理できていない
 ブロック内のスレッドの協調が不十分
原画像 処理画像
2015/12/02
int i,j, isub,jsub;
__shared__ int average;
__shared__ unsigned char cache[THREADX][THREADY];
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
cache[threadIdx.x][threadIdx.y] = p[i + WIDTH*j];
if(threadIdx.x == 0 && threadIdx.y == 0){
average = 0;
for(jsub = 0; jsub<mosaicSize; jsub++){
for(isub = 0; isub<mosaicSize; isub++){
average += cache[isub][jsub];
}
}
average /= (mosaicSize*mosaicSize);
}
filtered[i + WIDTH*j] = (unsigned char)average;
モザイク処理(共有メモリを利用)
GPGPU実践基礎工学52 2015/12/02
スレッド0 スレッド0以外
他のスレッドが共有メモリに
書き込む前にcache[][]に
アクセスする可能性がある
int i,j, isub,jsub;
__shared__ int average;
__shared__ unsigned char cache[THREADX][THREADY];
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
cache[threadIdx.x][threadIdx.y] = p[i + WIDTH*j];
if(threadIdx.x == 0 && threadIdx.y == 0){
average = 0;
for(jsub = 0; jsub<mosaicSize; jsub++){
for(isub = 0; isub<mosaicSize; isub++){
average += cache[isub][jsub];
}
}
average /= (mosaicSize*mosaicSize);
}
filtered[i + WIDTH*j] = (unsigned char)average;
モザイク処理(共有メモリを利用)
GPGPU実践基礎工学53 2015/12/02
スレッド0 スレッド0以外
スレッド0以外は平均値を計算しないので,直ちにこの行に到達し,
averageの値が確定する前に値を読んでfilteredに書き込む
可能性がある
ブロック内でのスレッドの同期
GPGPU実践基礎工学
 __syncthreads();
 カーネル実行中にスレッドの同期を取る
 __syncthreads()が書かれた行にスレッドが到達すると,同一ブ
ロック内の他の全てのスレッドがその行に達するまで待機
 異なるブロック間での同期は不可能
 ifの中に記述するとカーネルが終了しないことがある
if(条件){
__syncthreads();
//条件が真にならないスレッドはifの中に入らないため,
//カーネルが永久に終わらない
}
54 2015/12/02
int i,j, isub,jsub;
__shared__ int average;
__shared__ unsigned char cache[THREADX][THREADY];
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
cache[threadIdx.x][threadIdx.y] = p[i + WIDTH*j];
__syncthreads();
if(threadIdx.x == 0 && threadIdx.y == 0){
average = 0;
for(isub = 0; isub<mosaicSize; isub++){
for(jsub = 0; jsub<mosaicSize; jsub++){
average += cache[isub][jsub];
}
}
average /= (mosaicSize*mosaicSize);
}
__syncthreads();
filtered[i + WIDTH*j] = (unsigned char)average;
モザイク処理(共有メモリを利用)
GPGPU実践基礎工学55 2015/12/02
スレッド0 スレッド0以外
if文の前でブロック内の全
スレッドが同期しているので,
cache[][]には画素情報が
入っている
ブロック内で同期
スレッド0以外はif文を実行しないが,スレッド0が到達する(平
均値を計算し終わる)まで__syncthreads()で停止
ブロック内で同期
imageproc_mem.cu
実行結果
GPGPU実践基礎工学56
 正しく処理できている
 実行時間 260 ms(CPU) → 38.5 ms → 18.7 ms
 処理時間が約1/2に短縮
原画像 処理画像
2015/12/02
2次元的な配列アクセスの優先方向
GPGPU実践基礎工学57
 CUDAで2次元的に並列化してアクセス
する場合
 threadIdx.xのスレッド群(threadIdx.
yが一定)が連続なメモリアドレスにアクセ
ス
 C言語の多次元配列
 2次元目の要素が連続になるようメモリに
確保
 imageproc_mem.cuの共有メモリの使
い方は不適切
cache[THREADX][THREADY]
jsub
isub
threadIdx.x
threadIdx.y
p[],filtered[]
WIDTH
HEIGHT
j
i
threadIdx.x
threadIdx.y
THREADX
THREADY
2次元的な配列アクセスの優先方向
GPGPU実践基礎工学58
 共有メモリの宣言の変更
 1次元目と2次元目を入れ替え
 cache[THREADX][THREADY]
 cache[THREADY][THREADX]
 配列参照
 1次元目の添字はthreadIdx.yを利用
 2次元目の添字はthreadIdx.xを利用
 threadIdx.xのスレッド群(threadIdx.yが
一定)が連続なメモリアドレスにアクセス
cache[THREADX][THREADY]
jsub
isub
threadIdx.x
threadIdx.y
THREADX
THREADY
cache[THREADY][THREADX]
isub
jsub
threadIdx.y
threadIdx.x
THREADY
THREADX
__global__ void mosaic_shared
(unsigned char *p,unsigned char *filtered, int mosaicSize){
int i,j, isub,jsub;
__shared__ int average;
__shared__ unsigned char cache[THREADX][THREADY];
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
cache[threadIdx.x][threadIdx.y] = p[i + WIDTH*j];
__syncthreads(); 
if(threadIdx.x == 0 && threadIdx.y == 0){
average = 0;
for(isub = 0; isub<mosaicSize; isub++){
for(jsub = 0; jsub<mosaicSize; jsub++){
average += cache[isub][jsub];
}
}
average /= (mosaicSize*mosaicSize);
}
__syncthreads(); 
filtered[i + WIDTH*j] = (unsigned char)average;
}
モザイク処理(共有メモリを利用)
GPGPU実践基礎工学59 2015/12/02
__global__ void mosaic_shared_indexchage
(unsigned char *p,unsigned char *filtered, int mosaicSize){
int i,j, isub,jsub;
__shared__ int average;
__shared__ unsigned char cache[THREADY][THREADX];
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
cache[threadIdx.y][threadIdx.x] = p[i + WIDTH*j];
__syncthreads(); 
if(threadIdx.x == 0 && threadIdx.y == 0){
average = 0;
for(jsub = 0; jsub<mosaicSize; jsub++){
for(isub = 0; isub<mosaicSize; isub++){
average += cache[jsub][isub];
}
}
average /= (mosaicSize*mosaicSize);
}
__syncthreads(); 
filtered[i + WIDTH*j] = (unsigned char)average;
}
モザイク処理(共有メモリの添字を交換)
GPGPU実践基礎工学60 2015/12/02
実行結果(プロファイラ出力)
GPGPU実践基礎工学61
 ごくわずかに高速化(約20s)
 何回実行しても,mosaic_shared_indexchange()の実行
時間はmosaic_shared()より10~20s高速
 複数のスレッドが共有メモリにアクセスするのは,グローバル
メモリの読み込みのみ(この部分にだけ影響)
 処理の大半は各ブロックのスレッド0が逐次的にアクセス
2015/12/02
‐bash‐3.2$ cat cuda_profile_0.log
# CUDA_PROFILE_LOG_VERSION 2.0
# CUDA_DEVICE 3 Tesla M2050
# TIMESTAMPFACTOR fffff5e8528346d8
method,gputime,cputime,occupancy
method=[ memcpyHtoD ] gputime=[ 1.952 ] cputime=[ 42.000 ]
method=[ memcpyHtoD ] gputime=[ 1.728 ] cputime=[ 36.000 ]
method=[ memcpyHtoD ] gputime=[ 4572.224 ] cputime=[ 4822.000 ]
method=[ memcpyDtoD ] gputime=[ 384.800 ] cputime=[ 16.000 ]
method=[ _Z13mosaic_sharedPhS_i ] gputime=[ 18696.641 ] cputime=[ 8.000 ] occupancy=[ 1.000 ]
method=[ _Z25mosaic_shared_indexchangePhS_i ] gputime=[ 18677.984 ] cputime=[ 6.000 ] 
occupancy=[ 1.000 ]
method=[ memcpyDtoH ] gputime=[ 7602.752 ] cputime=[ 46164.000 ]
空間フィルタ
2015/12/02GPGPU実践基礎工学62
 ある画素とその周囲の画素を使って処理
 処理の仕方を規定したカーネルを定義
 カーネルは1次元配列で表現
原画像 輪郭抽出
0 1 0
1 ‐4 1
0 1 0
= b+d‐4e+f+h
フィルタ
(カーネル)
a b c
d e f
g h i
空間フィルタ
GPGPU実践基礎工学63
 カーネルは1次元配列で表現
 ぼかし(平均フィルタ)
 輪郭抽出
1/9 1/9 1/9
1/9 1/9 1/9
1/9 1/9 1/9
0 1 0
1 ‐4 1
0 1 0
float blur[9] ={1.0f/9.0f,1.0f/9.0f,1.0f/9.0f,
1.0f/9.0f,1.0f/9.0f,1.0f/9.0f,
1.0f/9.0f,1.0f/9.0f,1.0f/9.0f};
float laplacian[9] ={ 0.0f, 1.0f, 0.0f,
1.0f,‐4.0f, 1.0f,
0.0f, 1.0f, 0.0f};
2015/12/02
__global__ void boxfilter(unsigned char *p,unsigned char *filtered, float *filter){
int i,j;
int result = BLACK;
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  filter[0]*p[(i‐1) + WIDTH*(j‐1)]
+filter[1]*p[(i ) + WIDTH*(j‐1)]
+filter[2]*p[(i+1) + WIDTH*(j‐1)]
+filter[3]*p[(i‐1) + WIDTH*(j  )]
+filter[4]*p[(i ) + WIDTH*(j  )]
+filter[5]*p[(i+1) + WIDTH*(j  )]
+filter[6]*p[(i‐1) + WIDTH*(j+1)]
+filter[7]*p[(i ) + WIDTH*(j+1)]
+filter[8]*p[(i+1) + WIDTH*(j+1)];
}
if(result<BLACK) result = ‐result; //数値が負になっていれば‐1をかける
if(result>WHITE) result = WHITE;   //数値が255を超えていれば255に収める
filtered[i+WIDTH*j]  = (unsigned char)result;
}
空間フィルタ(前回授業で作成)
GPGPU実践基礎工学64 2015/12/02
imageproc.cu
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  filter[0]*p[(i‐1) + WIDTH*(j‐1)] +filter[1]*p[(i ) + WIDTH*(j‐1)]
+filter[2]*p[(i+1) + WIDTH*(j‐1)] +filter[3]*p[(i‐1) + WIDTH*(j  )]
+filter[4]*p[(i ) + WIDTH*(j  )] +filter[5]*p[(i+1) + WIDTH*(j  )]
+filter[6]*p[(i‐1) + WIDTH*(j+1)] +filter[7]*p[(i ) + WIDTH*(j+1)]
+filter[8]*p[(i+1) + WIDTH*(j+1)];
}
空間フィルタ(前回授業で作成)
GPGPU実践基礎工学65 2015/12/02
p[]filter[]
 メモリアクセス
 画像(配列p)へは複数スレッドが隣接し
たメモリアドレスにアクセス
 コアレスアクセス可能
 フィルタ(配列filter)へは複数スレッ
ドが同じ要素にアクセス
 コアレスアクセス不可能
 L2キャッシュに入る可能性はある
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  filter[0]*p[(i‐1) + WIDTH*(j‐1)] +filter[1]*p[(i ) + WIDTH*(j‐1)]
+filter[2]*p[(i+1) + WIDTH*(j‐1)] +filter[3]*p[(i‐1) + WIDTH*(j  )]
+filter[4]*p[(i ) + WIDTH*(j  )] +filter[5]*p[(i+1) + WIDTH*(j  )]
+filter[6]*p[(i‐1) + WIDTH*(j+1)] +filter[7]*p[(i ) + WIDTH*(j+1)]
+filter[8]*p[(i+1) + WIDTH*(j+1)];
}
空間フィルタ(前回授業で作成)
GPGPU実践基礎工学66 2015/12/02
p[]filter[]
 メモリアクセス
 画像(配列p)へは複数スレッドが隣接し
たメモリアドレスにアクセス
 コアレスアクセス可能
 フィルタ(配列filter)へは複数スレッ
ドが同じ要素にアクセス
 コアレスアクセス不可能
 L2キャッシュに入る可能性はある ij
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  filter[0]*p[(i‐1) + WIDTH*(j‐1)] +filter[1]*p[(i ) + WIDTH*(j‐1)]
+filter[2]*p[(i+1) + WIDTH*(j‐1)] +filter[3]*p[(i‐1) + WIDTH*(j  )]
+filter[4]*p[(i ) + WIDTH*(j  )] +filter[5]*p[(i+1) + WIDTH*(j  )]
+filter[6]*p[(i‐1) + WIDTH*(j+1)] +filter[7]*p[(i ) + WIDTH*(j+1)]
+filter[8]*p[(i+1) + WIDTH*(j+1)];
}
空間フィルタ(前回授業で作成)
GPGPU実践基礎工学67 2015/12/02
p[]filter[]
 メモリアクセス
 画像(配列p)へは複数スレッドが隣接し
たメモリアドレスにアクセス
 コアレスアクセス可能
 フィルタ(配列filter)へは複数スレッ
ドが同じ要素にアクセス
 コアレスアクセス不可能
 L2キャッシュに入る可能性はある ij
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  filter[0]*p[(i‐1) + WIDTH*(j‐1)] +filter[1]*p[(i ) + WIDTH*(j‐1)]
+filter[2]*p[(i+1) + WIDTH*(j‐1)] +filter[3]*p[(i‐1) + WIDTH*(j  )]
+filter[4]*p[(i ) + WIDTH*(j  )] +filter[5]*p[(i+1) + WIDTH*(j  )]
+filter[6]*p[(i‐1) + WIDTH*(j+1)] +filter[7]*p[(i ) + WIDTH*(j+1)]
+filter[8]*p[(i+1) + WIDTH*(j+1)];
}
空間フィルタ(前回授業で作成)
GPGPU実践基礎工学68 2015/12/02
p[]filter[]
 メモリアクセス
 画像(配列p)へは複数スレッドが隣接し
たメモリアドレスにアクセス
 コアレスアクセス可能
 フィルタ(配列filter)へは複数スレッ
ドが同じ要素にアクセス
 コアレスアクセス不可能
 L2キャッシュに入る可能性はある ij
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  filter[0]*p[(i‐1) + WIDTH*(j‐1)] +filter[1]*p[(i ) + WIDTH*(j‐1)]
+filter[2]*p[(i+1) + WIDTH*(j‐1)] +filter[3]*p[(i‐1) + WIDTH*(j  )]
+filter[4]*p[(i ) + WIDTH*(j  )] +filter[5]*p[(i+1) + WIDTH*(j  )]
+filter[6]*p[(i‐1) + WIDTH*(j+1)] +filter[7]*p[(i ) + WIDTH*(j+1)]
+filter[8]*p[(i+1) + WIDTH*(j+1)];
}
空間フィルタ(前回授業で作成)
GPGPU実践基礎工学69 2015/12/02
p[]filter[]
 メモリアクセス
 画像(配列p)へは複数スレッドが隣接し
たメモリアドレスにアクセス
 コアレスアクセス可能
 フィルタ(配列filter)へは複数スレッ
ドが同じ要素にアクセス
 コアレスアクセス不可能
 L2キャッシュに入る可能性はある ij
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  filter[0]*p[(i‐1) + WIDTH*(j‐1)] +filter[1]*p[(i ) + WIDTH*(j‐1)]
+filter[2]*p[(i+1) + WIDTH*(j‐1)] +filter[3]*p[(i‐1) + WIDTH*(j  )]
+filter[4]*p[(i ) + WIDTH*(j  )] +filter[5]*p[(i+1) + WIDTH*(j  )]
+filter[6]*p[(i‐1) + WIDTH*(j+1)] +filter[7]*p[(i ) + WIDTH*(j+1)]
+filter[8]*p[(i+1) + WIDTH*(j+1)];
}
空間フィルタ(前回授業で作成)
GPGPU実践基礎工学70 2015/12/02
p[]filter[]
 メモリアクセス
 画像(配列p)へは複数スレッドが隣接し
たメモリアドレスにアクセス
 コアレスアクセス可能
 フィルタ(配列filter)へは複数スレッ
ドが同じ要素にアクセス
 コアレスアクセス不可能
 L2キャッシュに入る可能性はある ij
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  filter[0]*p[(i‐1) + WIDTH*(j‐1)] +filter[1]*p[(i ) + WIDTH*(j‐1)]
+filter[2]*p[(i+1) + WIDTH*(j‐1)] +filter[3]*p[(i‐1) + WIDTH*(j  )]
+filter[4]*p[(i ) + WIDTH*(j  )] +filter[5]*p[(i+1) + WIDTH*(j  )]
+filter[6]*p[(i‐1) + WIDTH*(j+1)] +filter[7]*p[(i ) + WIDTH*(j+1)]
+filter[8]*p[(i+1) + WIDTH*(j+1)];
}
空間フィルタ(前回授業で作成)
GPGPU実践基礎工学71 2015/12/02
p[]filter[]
 メモリアクセス
 画像(配列p)へは複数スレッドが隣接し
たメモリアドレスにアクセス
 コアレスアクセス可能
 フィルタ(配列filter)へは複数スレッ
ドが同じ要素にアクセス
 コアレスアクセス不可能
 L2キャッシュに入る可能性はある ij
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  filter[0]*p[(i‐1) + WIDTH*(j‐1)] +filter[1]*p[(i ) + WIDTH*(j‐1)]
+filter[2]*p[(i+1) + WIDTH*(j‐1)] +filter[3]*p[(i‐1) + WIDTH*(j  )]
+filter[4]*p[(i ) + WIDTH*(j  )] +filter[5]*p[(i+1) + WIDTH*(j  )]
+filter[6]*p[(i‐1) + WIDTH*(j+1)] +filter[7]*p[(i ) + WIDTH*(j+1)]
+filter[8]*p[(i+1) + WIDTH*(j+1)];
}
空間フィルタ(前回授業で作成)
GPGPU実践基礎工学72 2015/12/02
p[]filter[]
 メモリアクセス
 画像(配列p)へは複数スレッドが隣接し
たメモリアドレスにアクセス
 コアレスアクセス可能
 フィルタ(配列filter)へは複数スレッ
ドが同じ要素にアクセス
 コアレスアクセス不可能
 L2キャッシュに入る可能性はある ij
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  filter[0]*p[(i‐1) + WIDTH*(j‐1)] +filter[1]*p[(i ) + WIDTH*(j‐1)]
+filter[2]*p[(i+1) + WIDTH*(j‐1)] +filter[3]*p[(i‐1) + WIDTH*(j  )]
+filter[4]*p[(i ) + WIDTH*(j  )] +filter[5]*p[(i+1) + WIDTH*(j  )]
+filter[6]*p[(i‐1) + WIDTH*(j+1)] +filter[7]*p[(i ) + WIDTH*(j+1)]
+filter[8]*p[(i+1) + WIDTH*(j+1)];
}
空間フィルタ(前回授業で作成)
GPGPU実践基礎工学73 2015/12/02
p[]filter[]
 メモリアクセス
 画像(配列p)へは複数スレッドが隣接し
たメモリアドレスにアクセス
 コアレスアクセス可能
 フィルタ(配列filter)へは複数スレッ
ドが同じ要素にアクセス
 コアレスアクセス不可能
 L2キャッシュに入る可能性はある ij
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  filter[0]*p[(i‐1) + WIDTH*(j‐1)] +filter[1]*p[(i ) + WIDTH*(j‐1)]
+filter[2]*p[(i+1) + WIDTH*(j‐1)] +filter[3]*p[(i‐1) + WIDTH*(j  )]
+filter[4]*p[(i ) + WIDTH*(j  )] +filter[5]*p[(i+1) + WIDTH*(j  )]
+filter[6]*p[(i‐1) + WIDTH*(j+1)] +filter[7]*p[(i ) + WIDTH*(j+1)]
+filter[8]*p[(i+1) + WIDTH*(j+1)];
}
空間フィルタ(前回授業で作成)
GPGPU実践基礎工学74 2015/12/02
p[]filter[]
 メモリアクセス
 画像(配列p)へは複数スレッドが隣接し
たメモリアドレスにアクセス
 コアレスアクセス可能
 フィルタ(配列filter)へは複数スレッ
ドが同じ要素にアクセス
 コアレスアクセス不可能
 キャッシュに入る可能性はある ij
空間フィルタ処理の高速化
GPGPU実践基礎工学75
 フィルタ(配列filter)へのアクセス
 コアレスアクセスできていない
 キャッシュに入る可能性は高いが,有効活用されているかは
不明
 GPUのキャッシュは空間局所性を利用
 配列filterへのアクセスの高速化
 共有メモリを利用すると処理が冗長
 1ブロックから9スレッドを選び,グローバルメモリから共有メモリへコ
ピーし,同期をとる処理を追加する必要がある
 コンスタントメモリが活用できる
2015/12/02
メモリの種類
 オフチップメモリ(GPUのチップ外部に置かれたメモリ)
 低速アクセス,大容量
 CPUから直接アクセス可能
 ローカルメモリだけはアクセス不可
GPGPU実践基礎工学76
グローバルメモリ ローカルメモリ テクスチャメモリ コンスタントメモリ
容量 大 小 大 小
速度 低速 低速 高速* 高速*
GPUからの
読み書き
読み書き可
全てのスレッドが同
じメモリにアクセス
読み書き可
各スレッドが異なる
メモリにアクセス
読み込み可
全てのスレッドが同
じメモリにアクセス
読み込み可
全てのスレッドが同
じメモリにアクセス
CPUからの
アクセス
読み書き可 読み書き不可 読み書き可 読み書き可
*キャッシュが効く場合
2015/12/02
コンスタントメモリ
 GPU全体で同じメモリにア
クセス
 コンスタントキャッシュを利
用することで,効率的な読
み込みが可能
 キャッシュはオンチップ
 GPU全体で64kB
2015/12/02GPGPU実践基礎工学77
L2キャッシュ
コンスタントメモリ
テクスチャメモリ
GPU
Chip
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
L1キャッ
シュ
共有
メモリ
SM
レジ
スタ
レジ
スタ
レジ
スタ
レジ
スタ
CUDA 
Core
CUDA 
Core
CUDA 
Core
CUDA 
Core
L1キャッ
シュ
共有
メモリ
SM
グローバルメモリ
ホスト
メモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
ローカル
メモリ
・・・
・・・
コンスタントメモリの宣言
 サイズは静的に決定
 __constant__ 型 変数名;
 __constant__ 型 変数名[要素数];
 配列としても宣言可能
 要素数はコンパイル時に確定している必要がある
 cudaMalloc()やcudaFree()は不要
 グローバル変数として宣言,複数のカーネルからアクセス
 読込専用のメモリならではの使い方
 書込可能なメモリでは厳禁
2015/12/02GPGPU実践基礎工学78
コンスタントメモリの利用
 メモリは読込専用
 CPUからは変更可能
 専用のメモリ転送命令でコピー
 cudaMemcpyToSymbol
 CPU上のメモリをコンスタントメモリにコピーする
 cudaMemcpyToSymbol(転送先変数名, 転送元アドレス,
バイト数, オフセット, 方向);
 オフセット,方向は無くてもよい
 オフセットを省略すると0が使われる
 方向を省略するとcudaMemcpyHostToDeviceが使われる
2015/12/02GPGPU実践基礎工学79
コンスタントメモリへのアクセス
(Tesla世代)
 コンスタントメモリへ高速にアクセスできる要因
1. ブロードキャストによるデータの分配
 16スレッド(Half Warp)単位でアクセスし,1回の読込を他
のスレッドにブロードキャストできる
 16スレッドが同じアドレスにアクセスすると最も効率がよい
2. コンスタントメモリキャッシュ
 SMごとに存在する独自のオンチップキャッシュ
 他のHalf Warpがキャッシュされたデータへアクセスしても,
コンスタントメモリからの読込が発生しない
2015/12/02GPGPU実践基礎工学80
コンスタントメモリへのアクセス
(Tesla世代)
 オフチップメモリ(DRAM)からの読込量を抑制
 オフチップメモリ(DRAM)からの読込による実行速度低
下を回避
 コンスタントメモリへのアクセスの制約
 Half Warp内のスレッド全てが異なるコンスタントメモリのア
ドレスを参照すると,読込が逐次化
 読込命令の処理に最悪で16倍の時間を要する
2015/12/02GPGPU実践基礎工学81
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0 0
コンスタントメモリへのアクセス
(Tesla世代)
 Half Warp内のスレッド全てが同じメモ
リアドレスにアクセス
 1スレッドの読込をブロードキャストによっ
て残りのスレッドが共有
 他のHalf Warpも同じメモリアドレスに
アクセス
 データがキャッシュされているため,キャッ
シュから高速に読み出し
2015/12/02GPGPU実践基礎工学82
Half Warp内でのスレッドID
メモリアドレス
メモリアドレスに対する
スレッドのアクセス要求
コンスタントメモリへのアクセス
(Tesla世代)
 Half Warp内のスレッド全てが異なる
メモリアドレスにアクセス
 読込が逐次化
 読込処理の時間は,Half Warpがアクセ
スするコンスタントメモリアドレスの数に比
例
 最悪で処理に16倍の時間がかかる
 おそらくグローバルメモリアクセスよりも遅くなる
2015/12/02GPGPU実践基礎工学83
15
14
13
12
11
10
9
8
7
6
5
4
3
2
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1 1
0 0
コンスタントメモリへのアクセス
(Fermi世代)
 コンスタントメモリへ高速にアクセスできる要因
1. ブロードキャストによるデータの分配
 32スレッド(Warp)単位でアクセスし,1回の読込を他のスレッ
ドにブロードキャストできる
 32スレッドが同じアドレスにアクセスすると最も効率がよい
2. コンスタントメモリキャッシュ
 SMごとに存在する独自のオンチップキャッシュ
 他のWarpがキャッシュされたデータへアクセスしても,コンス
タントメモリからの読込が発生しない
2015/12/02GPGPU実践基礎工学84
コンスタントメモリへのアクセス
(Fermi世代)
 オフチップメモリ(DRAM)からの読込量を抑制
 オフチップメモリ(DRAM)からの読込による実行速度低
下を回避
 コンスタントメモリへのアクセスの制約
 Warp内のスレッド全てが異なるコンスタントメモリのアドレス
を参照すると,読込が逐次化
 読込命令の処理に最悪で32倍の時間を要する
2015/12/02GPGPU実践基礎工学85
0 16 32 48 64 80 96 11
2
コンスタントメモリへのアクセス
(Fermi世代)
 Warp内のスレッド全てが同じコンスタントメモリアドレス
にアクセス
 1スレッドの読込をブロードキャストによって残りのスレッドが
共有
 他のWarpも同じメモリアドレスにアクセス
 データがキャッシュされているため,キャッシュから高速に読
み出し
2015/12/02GPGPU実践基礎工学86
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
メモリアドレスに対する
スレッドのアクセス要求
0 16 32 48 64 80 96 11
2
コンスタントメモリへのアクセス
(Fermi世代)
 Warp内のスレッド全てが異なるコンスタントメモリアドレ
スにアクセス
 読込が逐次化
 読込処理の時間は,Warpがアクセスするコンスタントメモリア
ドレスの数に比例
 最悪で処理に32倍の時間がかかる
 おそらくグローバルメモリアクセスよりも遅くなる
2015/12/02GPGPU実践基礎工学87
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
コンスタントメモリを使った空間フィルタ
の高速化
GPGPU実践基礎工学88
 空間フィルタに用いるカーネル
 1次元の配列として宣言,GPU(グローバルメモリ)へ転送
 (端を除く)全スレッドからアクセス
 値は固定値で,GPUから書き換えない
 コンスタントメモリを利用
 1次元の配列として宣言,GPU(コンスタントメモリ)へ転送
 全スレッドがコンスタントメモリにアクセス
 コンスタントキャッシュが有効利用される
2015/12/02
メイン関数
(コンスタントメモリの宣言と転送)
GPGPU実践基礎工学89
:(省略)
:
__constant__ float cfilter[9];//コンスタントメモリにフィルタのカーネル分のメモリを確保
//mainの外で宣言しているので,どの関数からもアクセス可能
int main(void){
:(省略)
float laplacian[9] ={ 0.0f, 1.0f, 0.0f,
1.0f,‐4.0f, 1.0f,
0.0f, 1.0f, 0.0f};
//グローバルメモリに確保していたフィルタのカーネルは不要
//float *filter;
//cudaMalloc( (void **)&filter, sizeof(float)*9);
//cudaMemcpy(filter, laplacian, sizeof(float)*9, cudaMemcpyHostToDevice);
//コンスタントメモリにフィルタのカーネルを送る
cudaMemcpyToSymbol(cfilter, laplacian, sizeof(float)*9);
:(省略)
boxfilter_constant<<<block,thread>>>(dev_p,dev_filtered);
:(省略)
}
2015/12/02
imageproc_mem.cu
__global__ void boxfilter_constant(unsigned char *p, unsigned char *filtered){
int i,j;
int result = BLACK;
i = blockIdx.x*blockDim.x + threadIdx.x;
j = blockIdx.y*blockDim.y + threadIdx.y;
if(0<i && i<WIDTH‐1 && 0<j && j<HEIGHT‐1){ //端の画素は処理をしないため,ifで処理を分岐
result =  cfilter[0]*p[(i‐1) + WIDTH*(j‐1)]
+cfilter[1]*p[(i ) + WIDTH*(j‐1)]
+cfilter[2]*p[(i+1) + WIDTH*(j‐1)]
+cfilter[3]*p[(i‐1) + WIDTH*(j  )]
+cfilter[4]*p[(i ) + WIDTH*(j  )]
+cfilter[5]*p[(i+1) + WIDTH*(j  )]
+cfilter[6]*p[(i‐1) + WIDTH*(j+1)]
+cfilter[7]*p[(i ) + WIDTH*(j+1)]
+cfilter[8]*p[(i+1) + WIDTH*(j+1)];
}
if(result<BLACK) result = ‐result; //数値が負になっていれば‐1をかける
if(result>WHITE) result = WHITE;   //数値が255を超えていれば255に収める
filtered[i+WIDTH*j]  = (unsigned char)result;
}
空間フィルタ(コンスタントメモリ利用)
GPGPU実践基礎工学90 2015/12/02
imageproc_mem.cu
実行結果
GPGPU実践基礎工学91
 実行時間 553 ms(CPU) → 4.13 ms → 3.38 ms
 CPUからかなり高速化されていたが,さらに2割短縮
原画像 処理画像
2015/12/02

More Related Content

PDF
CUDAプログラミング入門
PDF
1076: CUDAデバッグ・プロファイリング入門
PDF
2015年度GPGPU実践プログラミング 第5回 GPUのメモリ階層
PDF
2015年度先端GPGPUシミュレーション工学特論 第4回 GPUのメモリ階層の詳細 (共有メモリ)
PPTX
RustによるGPUプログラミング環境
PDF
深層学習の新しい応用と、 それを支える計算機の進化 - Preferred Networks CEO 西川徹 (SEMICON Japan 2022 Ke...
PDF
2015年度GPGPU実践プログラミング 第10回 行列計算(行列-行列積の高度な最適化)
PDF
2015年度先端GPGPUシミュレーション工学特論 第5回 GPUのメモリ階層の詳細 (様々なメモリの利用)
CUDAプログラミング入門
1076: CUDAデバッグ・プロファイリング入門
2015年度GPGPU実践プログラミング 第5回 GPUのメモリ階層
2015年度先端GPGPUシミュレーション工学特論 第4回 GPUのメモリ階層の詳細 (共有メモリ)
RustによるGPUプログラミング環境
深層学習の新しい応用と、 それを支える計算機の進化 - Preferred Networks CEO 西川徹 (SEMICON Japan 2022 Ke...
2015年度GPGPU実践プログラミング 第10回 行列計算(行列-行列積の高度な最適化)
2015年度先端GPGPUシミュレーション工学特論 第5回 GPUのメモリ階層の詳細 (様々なメモリの利用)

What's hot (20)

PDF
2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)
PDF
プログラムを高速化する話Ⅱ 〜GPGPU編〜
PDF
2015年度先端GPGPUシミュレーション工学特論 第15回 CPUとGPUの協調
PPTX
【DL輪読会】"Instant Neural Graphics Primitives with a Multiresolution Hash Encoding"
PPTX
モデル高速化百選
PPTX
Tensor コアを使った PyTorch の高速化
ODP
ぷよぷよAIの新しい探索法
PDF
いまさら聞けない!CUDA高速化入門
PDF
2015年度GPGPU実践プログラミング 第2回 GPUのアーキテクチャとプログラム構造
PDF
モデルアーキテクチャ観点からのDeep Neural Network高速化
PDF
2015年度先端GPGPUシミュレーション工学特論 第2回 GPUによる並列計算の概念と メモリアクセス
PDF
ARM CPUにおけるSIMDを用いた高速計算入門
PDF
Chainer で Tensor コア (fp16) を使いこなす
PDF
中3女子でもわかる constexpr
PDF
カスタムSIで使ってみよう ~ OpenAI Gym を使った強化学習
PPTX
【DL輪読会】HexPlaneとK-Planes
PPTX
[DL輪読会]Pixel2Mesh: Generating 3D Mesh Models from Single RGB Images
PPTX
近年のHierarchical Vision Transformer
PPTX
分散深層学習 @ NIPS'17
PPTX
本当は恐ろしい分散システムの話
2015年度GPGPU実践プログラミング 第9回 行列計算(行列-行列積)
プログラムを高速化する話Ⅱ 〜GPGPU編〜
2015年度先端GPGPUシミュレーション工学特論 第15回 CPUとGPUの協調
【DL輪読会】"Instant Neural Graphics Primitives with a Multiresolution Hash Encoding"
モデル高速化百選
Tensor コアを使った PyTorch の高速化
ぷよぷよAIの新しい探索法
いまさら聞けない!CUDA高速化入門
2015年度GPGPU実践プログラミング 第2回 GPUのアーキテクチャとプログラム構造
モデルアーキテクチャ観点からのDeep Neural Network高速化
2015年度先端GPGPUシミュレーション工学特論 第2回 GPUによる並列計算の概念と メモリアクセス
ARM CPUにおけるSIMDを用いた高速計算入門
Chainer で Tensor コア (fp16) を使いこなす
中3女子でもわかる constexpr
カスタムSIで使ってみよう ~ OpenAI Gym を使った強化学習
【DL輪読会】HexPlaneとK-Planes
[DL輪読会]Pixel2Mesh: Generating 3D Mesh Models from Single RGB Images
近年のHierarchical Vision Transformer
分散深層学習 @ NIPS'17
本当は恐ろしい分散システムの話
Ad

Viewers also liked (20)

PDF
2015年度先端GPGPUシミュレーション工学特論 第8回 偏微分方程式の差分計算 (拡散方程式)
PDF
2015年度先端GPGPUシミュレーション工学特論 第3回 GPUプログラム構造の詳細 (threadとwarp)
PDF
2015年度先端GPGPUシミュレーション工学特論 第6回 プログラムの性能評価指針 (Flop/Byte,計算律速,メモリ律速)
PDF
2015年度先端GPGPUシミュレーション工学特論 第9回 偏微分方程式の差分計算 (移流方程式)
PDF
2015年度先端GPGPUシミュレーション工学特論 第7回 総和計算(Atomic演算)
PDF
2015年度先端GPGPUシミュレーション工学特論 第1回補足 GPGPU教育計算機システムGROUSEの利用方法
PDF
2015年度GPGPU実践基礎工学 第6回 ソフトウェアによるCPUの高速化技術
PDF
2015年度GPGPU実践基礎工学 第9回補足 GROUSEの利用方法
PDF
2015年度GPGPU実践基礎工学 第12回 GPUによる画像処理
PDF
2015年度先端GPGPUシミュレーション工学特論 第1回 先端シミュレーションおよび産業界におけるGPUの役割
PDF
2015年度GPGPU実践基礎工学 第7回 シングルコアとマルチコア
PDF
2015年度GPGPU実践プログラミング 第7回 総和計算
PDF
2015年度GPGPU実践基礎工学 第1回 学際的分野における先端シミュレーション技術の歴史
PDF
2015年度GPGPU実践プログラミング 第14回 N体問題
PDF
2015年度GPGPU実践プログラミング 第13回 多粒子の運動
PDF
2015年度GPGPU実践プログラミング 第11回 画像処理
PDF
2015年度GPGPU実践基礎工学 第4回 CPUのアーキテクチャ
PDF
2015年度GPGPU実践基礎工学 第8回 並列計算の概念 (プロセスとスレッド)
PDF
2015年度GPGPU実践基礎工学 第3回 GPUクラスタ上でのプログラミング(CUDA)
PDF
2015年度GPGPU実践プログラミング 第8回 総和計算(高度な最適化)
2015年度先端GPGPUシミュレーション工学特論 第8回 偏微分方程式の差分計算 (拡散方程式)
2015年度先端GPGPUシミュレーション工学特論 第3回 GPUプログラム構造の詳細 (threadとwarp)
2015年度先端GPGPUシミュレーション工学特論 第6回 プログラムの性能評価指針 (Flop/Byte,計算律速,メモリ律速)
2015年度先端GPGPUシミュレーション工学特論 第9回 偏微分方程式の差分計算 (移流方程式)
2015年度先端GPGPUシミュレーション工学特論 第7回 総和計算(Atomic演算)
2015年度先端GPGPUシミュレーション工学特論 第1回補足 GPGPU教育計算機システムGROUSEの利用方法
2015年度GPGPU実践基礎工学 第6回 ソフトウェアによるCPUの高速化技術
2015年度GPGPU実践基礎工学 第9回補足 GROUSEの利用方法
2015年度GPGPU実践基礎工学 第12回 GPUによる画像処理
2015年度先端GPGPUシミュレーション工学特論 第1回 先端シミュレーションおよび産業界におけるGPUの役割
2015年度GPGPU実践基礎工学 第7回 シングルコアとマルチコア
2015年度GPGPU実践プログラミング 第7回 総和計算
2015年度GPGPU実践基礎工学 第1回 学際的分野における先端シミュレーション技術の歴史
2015年度GPGPU実践プログラミング 第14回 N体問題
2015年度GPGPU実践プログラミング 第13回 多粒子の運動
2015年度GPGPU実践プログラミング 第11回 画像処理
2015年度GPGPU実践基礎工学 第4回 CPUのアーキテクチャ
2015年度GPGPU実践基礎工学 第8回 並列計算の概念 (プロセスとスレッド)
2015年度GPGPU実践基礎工学 第3回 GPUクラスタ上でのプログラミング(CUDA)
2015年度GPGPU実践プログラミング 第8回 総和計算(高度な最適化)
Ad

Similar to 2015年度GPGPU実践基礎工学 第13回 GPUのメモリ階層 (20)

PDF
2015年度GPGPU実践基礎工学 第14回 GPGPU組込開発環境
PDF
20170421 tensor flowusergroup
PPTX
並列計算への道 2015年版
PDF
20170726 py data.tokyo
PDF
機械学習とこれを支える並列計算: ディープラーニング・スーパーコンピューターの応用について
PPTX
JTAGを使ってみよう
PDF
High speed-pc-router 201505
PDF
【A-1】AIを支えるGPUコンピューティングの今
PDF
【関東GPGPU勉強会#4】GTX 1080でComputer Vision アルゴリズムを色々動かしてみる
PDF
IEEE ITSS Nagoya Chapter NVIDIA
PDF
1070: CUDA プログラミング入門
PDF
IEICE technical report (RECONF), January 2015.
PDF
GPUディープラーニング最新情報
PDF
NVIDIA 更新情報: Tesla P100 PCIe/cuDNN 5.1
PDF
POWER8ここだけの話
KEY
GPGPU deいろんな問題解いてみた
PDF
PEZY-SC2上における倍々精度Rgemmの実装と評価
PDF
A100 GPU 搭載! P4d インスタンス 使いこなしのコツ
PDF
第162回情報処理学会ハイパフォーマンスコンピューティング研究発表会
2015年度GPGPU実践基礎工学 第14回 GPGPU組込開発環境
20170421 tensor flowusergroup
並列計算への道 2015年版
20170726 py data.tokyo
機械学習とこれを支える並列計算: ディープラーニング・スーパーコンピューターの応用について
JTAGを使ってみよう
High speed-pc-router 201505
【A-1】AIを支えるGPUコンピューティングの今
【関東GPGPU勉強会#4】GTX 1080でComputer Vision アルゴリズムを色々動かしてみる
IEEE ITSS Nagoya Chapter NVIDIA
1070: CUDA プログラミング入門
IEICE technical report (RECONF), January 2015.
GPUディープラーニング最新情報
NVIDIA 更新情報: Tesla P100 PCIe/cuDNN 5.1
POWER8ここだけの話
GPGPU deいろんな問題解いてみた
PEZY-SC2上における倍々精度Rgemmの実装と評価
A100 GPU 搭載! P4d インスタンス 使いこなしのコツ
第162回情報処理学会ハイパフォーマンスコンピューティング研究発表会

More from 智啓 出川 (20)

PDF
Fortranが拓く世界、VSCodeが架ける橋
PDF
Very helpful python code to find coefficients of the finite difference method
PDF
Why do we confuse String and Array of Characters in Fortran?
PDF
Pythonによる累乗近似
PDF
数値計算結果のPythonによる後処理について(1次元データのピーク値およびその位置の推定)
PDF
オブジェクト指向Fortranが拓く(はずだった)新しい世界
PPTX
Schematic diagrams of GPUs' architecture and Time evolution of theoretical FL...
PDF
GPGPU Seminar (GPU Accelerated Libraries, 3 of 3, Thrust)
PDF
GPGPU Seminar (GPU Accelerated Libraries, 2 of 3, cuSPARSE)
PDF
GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)
PDF
GPGPU Education at Nagaoka University of Technology: A Trial Run
PDF
Cuda fortranの利便性を高めるfortran言語の機能
PDF
PGI CUDA FortranとGPU最適化ライブラリの一連携法
PPTX
教育機関でのJetsonの活用の可能性
PDF
GPGPU Seminar (GPGPU and CUDA Fortran)
PDF
GPGPU Seminar (Accelerataion of Lattice Boltzmann Method using CUDA Fortran)
PDF
GPGPU Seminar (PyCUDA)
PDF
2015年度先端GPGPUシミュレーション工学特論 第14回 複数GPUの利用
PDF
2015年度先端GPGPUシミュレーション工学特論 第13回 数値流体力学への応用 (高度な最適化)
PDF
2015年度先端GPGPUシミュレーション工学特論 第11回 数値流体力学への応用 (支配方程式,CPUプログラム)
Fortranが拓く世界、VSCodeが架ける橋
Very helpful python code to find coefficients of the finite difference method
Why do we confuse String and Array of Characters in Fortran?
Pythonによる累乗近似
数値計算結果のPythonによる後処理について(1次元データのピーク値およびその位置の推定)
オブジェクト指向Fortranが拓く(はずだった)新しい世界
Schematic diagrams of GPUs' architecture and Time evolution of theoretical FL...
GPGPU Seminar (GPU Accelerated Libraries, 3 of 3, Thrust)
GPGPU Seminar (GPU Accelerated Libraries, 2 of 3, cuSPARSE)
GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)
GPGPU Education at Nagaoka University of Technology: A Trial Run
Cuda fortranの利便性を高めるfortran言語の機能
PGI CUDA FortranとGPU最適化ライブラリの一連携法
教育機関でのJetsonの活用の可能性
GPGPU Seminar (GPGPU and CUDA Fortran)
GPGPU Seminar (Accelerataion of Lattice Boltzmann Method using CUDA Fortran)
GPGPU Seminar (PyCUDA)
2015年度先端GPGPUシミュレーション工学特論 第14回 複数GPUの利用
2015年度先端GPGPUシミュレーション工学特論 第13回 数値流体力学への応用 (高度な最適化)
2015年度先端GPGPUシミュレーション工学特論 第11回 数値流体力学への応用 (支配方程式,CPUプログラム)

2015年度GPGPU実践基礎工学 第13回 GPUのメモリ階層