TSUBAMEのTeslaを用いたGPGPU(CUDAの基礎)

Similar documents
TSUBAMEのTeslaを用いたGPGPU(CUDAの基礎)

TSUBAMEのTeslaを用いたGPGPU(CUDAの基礎)

TSUBAME2.0におけるGPUの 活用方法

Slide 1

Slide 1

1. GPU コンピューティング GPU コンピューティング GPUによる 汎用コンピューティング GPU = Graphics Processing Unit CUDA Compute Unified Device Architecture NVIDIA の GPU コンピューティング環境 Lin

07-二村幸孝・出口大輔.indd

CUDA を用いた画像処理 画像処理を CUDA で並列化 基本的な並列化の考え方 目標 : 妥当な Naïve コードが書ける 最適化の初歩がわかる ブロックサイズ メモリアクセスパターン

NUMAの構成

Microsoft PowerPoint - GPGPU実践基礎工学(web).pptx

( CUDA CUDA CUDA CUDA ( NVIDIA CUDA I

TSUBAME2.0 における GPU の 活用方法 東京工業大学学術国際情報センター丸山直也第 10 回 GPU コンピューティング講習会 2011 年 9 月 28 日

GPU CUDA CUDA 2010/06/28 1

Microsoft PowerPoint - GPGPU実践基礎工学(web).pptx

GPU.....

GPU GPU CPU CPU CPU GPU GPU N N CPU ( ) 1 GPU CPU GPU 2D 3D CPU GPU GPU GPGPU GPGPU 2 nvidia GPU CUDA 3 GPU 3.1 GPU Core 1

GPU 画像 動画処理用ハードウェア 低性能なプロセッサがたくさん詰まっている ピーク性能が非常に高い GPUを数値計算に用いるのがGPGPU Graphics Processing Unit General Purpose GPU TSUBAME2.0: GPUスパコン 本演習ではNVIDIA社の

Slides: TimeGraph: GPU Scheduling for Real-Time Multi-Tasking Environments

memo

memo

CUDA 連携とライブラリの活用 2

untitled

熊本大学学術リポジトリ Kumamoto University Repositor Title GPGPU による高速演算について Author(s) 榎本, 昌一 Citation Issue date Type URL Presentation

Microsoft PowerPoint - GPU_computing_2013_01.pptx

GPUコンピューティング講習会パート1

Microsoft PowerPoint - suda.pptx

GPU のアーキテクチャとプログラム構造 長岡技術科学大学電気電子情報工学専攻出川智啓

memo

概要 目的 CUDA Fortran の利用に関する基本的なノウハウを提供する 本チュートリアル受講後は Web 上で公開されている資料等を参照しながら独力で CUDA Fortran が利用できることが目標 対象 CUDA Fortran の利用に興味を抱いている方 前提とする知識 Fortran

プログラミング実習I

1. マシンビジョンにおける GPU の活用

GPGPUイントロダクション

GPGPUクラスタの性能評価

NUMAの構成

第1回 プログラミング演習3 センサーアプリケーション

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

ストリームを用いたコンカレントカーネルプログラミングと最適化 エヌビディアジャパン CUDAエンジニア森野慎也 GTC Japan 2014

slide5.pptx

AquesTalk プログラミングガイド

スライド 1

2011 年 3 月 3 日 GPGPU ハンズオンプログラミング演習 株式会社クロスアビリティ ability.jp 3 Mar 2011 Copyright (C) 2011 X-Ability Co.,Ltd. All rights reserved.

CUDA基礎1

PGIコンパイラ導入手順

Microsoft PowerPoint - OpenMP入門.pptx

GPU チュートリアル :OpenACC 篇 Himeno benchmark を例題として 高エネルギー加速器研究機構 (KEK) 松古栄夫 (Hideo Matsufuru) 1 December 2018 HPC-Phys 理化学研究所 共通コードプロジェクト

Microsoft PowerPoint - CproNt02.ppt [互換モード]

プログラミングI第10回

untitled

program7app.ppt

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

Microsoft PowerPoint - kougi7.ppt

3次多項式パラメタ推定計算の CUDAを用いた実装 (CUDAプログラミングの練習として) Implementation of the Estimation of the parameters of 3rd-order-Polynomial with CUDA

Microsoft PowerPoint pptx

AquesTalk2 Win マニュアル

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

4 倍精度基本線形代数ルーチン群 QPBLAS の紹介 [index] 1. Introduction 2. Double-double algorithm 3. QPBLAS 4. QPBLAS-GPU 5. Summary 佐々成正 1, 山田進 1, 町田昌彦 1, 今村俊幸 2, 奥田洋司

Microsoft Word - Cプログラミング演習(12)

AquesTalk Win Manual

ex04_2012.ppt

2006年10月5日(木)実施

Prog1_12th

PowerPoint プレゼンテーション

AquesTalk for WinCE プログラミングガイド

Taro-リストⅢ(公開版).jtd

演算増幅器

cp-7. 配列

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

Microsoft Word - matlab-coder-code-generation-quick-start-guide-japanese-r2016a

Microsoft PowerPoint - sales2.ppt

kiso2-03.key

Microsoft PowerPoint - kougi9.ppt

Microsoft PowerPoint - 計算機言語 第7回.ppt

tabaicho3mukunoki.pptx

1 OpenCL OpenCL 1 OpenCL GPU ( ) 1 OpenCL Compute Units Elements OpenCL OpenCL SPMD (Single-Program, Multiple-Data) SPMD OpenCL work-item work-group N

PowerPoint プレゼンテーション

Taro-ポインタ変数Ⅰ(公開版).j

PowerPoint Presentation

PowerPoint Presentation

Microsoft PowerPoint - lec10.ppt

NUMAの構成

Taro-ファイル処理(公開版).jtd

ex05_2012.pptx

01-introduction.ppt

N08

Microsoft PowerPoint ppt

昨年度までの研究紹介 および 研究計画

02: 変数と標準入出力

GPUコンピューティング講習会パート1

Microsoft Word - nvsi_050110jp_netvault_vtl_on_dothill_sannetII.doc

Microsoft PowerPoint - KHPCSS pptx

Operating System 仮想記憶

Microsoft PowerPoint - 11.pptx

Prog1_10th

スライド 1

Microsoft PowerPoint - 09.pptx

いまからはじめる組み込みGPU実装

CPU Levels in the memory hierarchy Level 1 Level 2... Increasing distance from the CPU in access time Level n Size of the memory at each level 1: 2.2

AquesTalk2 Linux マニュアル

gengo1-12

Microsoft Word - openmp-txt.doc

Transcription:

GPU コンピューティング (CUDA) 講習会 CUDA プログラミング基礎 丸山直也 2010/09/13 1

はじめに 本講習では時間の関係上ごくごく基礎的な内容のみをとりあげます ただし 資料の後半にはメモリアクセスなどに関するチューニングに向けた情報をのせてあります それらは講習時間内には取り上げません チューニングやよりアドバンストな内容の講習会は別途開催しております 本講習で取り上げる概念等は基礎的なものに限られるため CUDA に限らず OpenCL プログラミングにも有効です 2010/09/13 2

TSUBAME の Tesla 利用方法 : ログイン 1. 端末 (imac) へのログイン 配布したゲストアカウント用紙 1 枚目に記載されている ID パスワードを利用 2. Titech2006 もしくは 移動 ユーティリティを選択し X11.app を起動 (xterm の起動 ) 3. Tsubame へログイン 1. 配布したゲストアカウント用紙 3 枚目に記載されている ID, パスワードを利用 > ssh Y t login 名 @login.cc.titech.ac.jp tesladebug ただしあくまで開発用ノードなので 長時間に渡るプログラムは実行しないでください 本格的なプログラムは占有キューが利用してください 2010/09/13 3

講習会サンプルコード /work/nmaruyam/gpu-tutorial/ 以下にサンプルコードをおいてあります 各自のホームディレクトリにコピーしてください $ cd $ cp /work/nmaruyam/gpu-tutorial/gpu-tutorial.zip. $ unzip gpu-tutorial.zip 講習会ホームページにも掲載します 2010/09/13 4

1. CUDA 概要 2. CUDAプログラム例 3. 実行 4. 並列化 5. 同期 6. 最適化 7. 参考資料 目次 2010/09/13 5

CUDA を実行可能な GPU NVIDIA による G80 系アーキテクチャ以降の GPU 例 : GeForce 8800 GTX ( コアアーキテクチャ G80), GeForce 285 GTX ( コアアーキテクチャ GT200), Tesla S1070 (TSUBAME) 以下の URL に CUDA 対応 GPU 全リスト有り http://www.nvidia.com/object/cuda_learn_ products.html 2010/09/13 6

Fermi GPU NVIDIA の最新 GPU アーキテクチャ ハードウェア & ソフトウェアの大幅拡張 Tesla C/S/M 20XX 系 TSUBAME 2 に導入予定 GeForce 4XX 系 安い GTS450 150 ドル以下 コンパクト これから CUDA はじめるなら Fermi のみ対象とするのが簡単 2010/09/13 7

TSUBAME の GPU スペック telsadebug キューにログイン ssh t user@login.cc.titech.ac.jp tesladebug 以下のように devicequery プログラムを実行 nmaruyam@tgg075054:~> /work/gpu/maruyama/devicequery There are 4 devices supporting CUDA Device 0: "Tesla T10 Processor" Major revision number: 1 Minor revision number: 3 Total amount of global memory: 4294705152 bytes Number of multiprocessors: 30 Number of cores: 240 Total amount of constant memory: 65536 bytes Total amount of shared memory per block: 16384 bytes Total number of registers available per block: 16384 Warp size: 32 Maximum number of threads per block: 512 Maximum sizes of each dimension of a block: 512 x 512 x 64 Maximum sizes of each dimension of a grid: 65535 x 65535 x 1 Maximum memory pitch: 262144 bytes Texture alignment: 256 bytes Clock rate: 1.44 GHz 2010/09/13 Concurrent copy and execution: Yes 8

GPU による高速化手法 BLAS/FFT ライブラリを利用 CUDAプログラムを書く必要なし 手軽な高速化 本講習の最後にCUBLAS/CUFFTの使い方を説明 PGI による GPGPU 対応コンパイラを利用 半自動 CUDA 化コンパイラ (like OpenMP) 手軽 性能そこそこ CUDA/OpenCL でプログラミング CUDA/OpenCLを覚える必要あり 自由度最大 効果大 2010/09/13 9

プログラミング言語としての CUDA MPI のような SPMD プログラミングモデル ただし一部 SIMD のような制限有り 標準 C 言語サブセット +GPGPU 用拡張機能 他言語からの利用は通常の C プログラム呼び出し方法により可能 2007 年 2 月に最初のリリース 現在 v3.1 が最新リリース版 Tsubame では v2.3 が利用可能 v3 以降の多くの新機能は Fermi のみ対応 Windows Linux, Mac OS X+CUDA 対応 NVIDIA GPU の組み合わせで利用可能 現状の GPGPU で最も普及 Cf. Brook+, OpenCL, RapidMind, etc. 2010/09/13 10

プログラム例 : inc_seq int 型配列の全要素を 1 インクリメント プログラムリスト : inc_seq.cu #include <stdio.h> #include <stdlib.h> #include <cuda.h> #include <cuda_runtime.h> #define N (32) global void inc(int *array, int len) { int i; for (i = 0; i < len; i++) array[i]++; return; } int main(int argc, char *argv[]) { int i; int arrayh[n]; int *arrayd; size_t array_size; } for (i=0; i<n; i++) arrayh[i] = i; printf( input: ); for (i=0; i<n; i++) printf( %d, arrayh[i]); printf( n ); array_size = sizeof(int) * N; cudamalloc((void **)&arrayd, array_size); cudamemcpy(arrayd, arrayh, array_size, cudamemcpyhosttodevice); inc<<<1, 1>>>(arrayD, N); cudamemcpy(arrayh, arrayd, array_size, cudamemcpydevicetohost); printf( output: ); for (i=0; i<n; i++) printf( %d, arrayh[i]); printf( n ); return 0; 2010/09/13 11

ホストプログラム プログラム構成 + GPU カーネル関数 ホストプログラム CPU 上で実行されるプログラム ほぼ通常の C 言語として実装 GPU に対してデータ転送 プログラム呼び出しを実行 (GPU) カーネル関数 GPU 上で実行されるプログラム ホストプログラムから呼び出されて実行 再帰 関数ポインタは非サポート 2010/09/13 12

典型的な制御とデータの流れ @ CPU @ GPU GPU 側メモリにデータ用領域を確保 入力データを GPU へ転送 GPU カーネル関数を呼び出し 出力を CPU 側メモリへ転送 kernel_func() { } return; 入力 出力 入力 出力 CPU 側メモリ ( メインメモリ ) GPU 側メモリ ( デバイスメモリ ) 2010/09/13 13

@CPU: GPU 側メモリ領域確保 cudamalloc(void **devptr, size_t count) GPU 側メモリ ( デバイスメモリ グローバルメモリと呼ばれる ) に領域を確保 devptr: デバイスメモリアドレスへのポインタ 確保したメモリのアドレスが書き込まれる count: 領域のサイズ cudafree(void *devptr) 指定領域を開放 例 : 長さ 1024 の int の配列を確保 #define N (1024) int *arrayd; cudamalloc((void **)&arrayd, sizeof(int) * N); // arrayd has the address of allocated device memory 2010/09/13 14

@CPU: 入力データ転送 cudamemcpy(void *dst, const void *src, size_t count, enum cudamemcpykind kind) 先に cudamalloc で確保した領域に指定した CPU 側メモリのデータをコピー dst: 転送先デバイスメモリ src: 転送元 CPU メモリ kind: 転送タイプを指定する定数 ここでは cudamemcpyhosttodevice を与える 例 : 先に確保した領域へ CPU 上のデータ arrayh を転送 int arrayh[n]; cudamemcpy(arrayd, arrayh, sizeof(int)*n, cudamemcpyhosttodevice); 2010/09/13 15

@CPU: GPU カーネルの呼び出し kernel_func<<<grid_dim, block_dim>>>(kernel_param1, ); kernel_func: カーネル関数名 kernel_param: カーネル関数の引数 例 : カーネル関数 inc を呼び出し 入力配列の長さ inc<<<1, 1>>>(arrayD, N); 後述 入力配列へのポインタ 2010/09/13 16

@GPU: カーネル関数 GPU 上で実行される関数 GPU 側メモリのみアクセス可 CPU 側メモリはアクセス不可 引数利用可能 値の返却は不可 例 : int 型配列をインクリメントするカーネル関数 global void inc(int *array, int len) { int i; for (i = 0; i < len; i++) array[i]++; } 2010/09/13 17

@CPU: 結果の返却 入力転送と同様に cudamemcpy を用いる ただし 転送タイプは cudamemcpydevicetohost を指定 例 : インクリメントされた配列を CPU 側メモリへ転送 cudamemcpy(arrayh, arrayd, sizeof(int)*n, cudamemcpydevicetohost); 2010/09/13 18

プログラム例 : inc_seq int 型配列の全要素を 1 インクリメント プログラムリスト : inc_seq.cu #include <stdio.h> #include <stdlib.h> #include <cuda.h> #include <cuda_runtime.h> #define N (32) global void inc(int *array, int len) { int i; for (i = 0; i < len; i++) array[i]++; return; } int main(int argc, char *argv[]) { int i; int arrayh[n]; int *arrayd; size_t array_size; } for (i=0; i<n; i++) arrayh[i] = i; printf( input: ); for (i=0; i<n; i++) printf( %d, arrayh[i]); printf( n ); array_size = sizeof(int) * N; cudamalloc((void **)&arrayd, array_size); cudamemcpy(arrayd, arrayh, array_size, cudamemcpyhosttodevice); inc<<<1, 1>>>(arrayD, N); cudamemcpy(arrayh, arrayd, array_size, cudamemcpydevicetohost); printf( output: ); for (i=0; i<n; i++) printf( %d, arrayh[i]); printf( n ); return 0; 2010/09/13 19

プログラム例 : 行列積 (1) プログラムリスト : /work/gpu/maruyama/matmul/matmul_seq.cu #include <stdio.h> #include <stdlib.h> #include <cuda.h> #include <cuda_runtime.h> #define L (1024) #define M (1024) #define N (1024) global void matmul(float *A, float *B, float *C, int l, int m, int n) { int i, j, k; for (i = 0; i < l; i++) { for (j = 0; j < n; j++) { float sum = 0.0; for (k = 0; k < m; k++) { sum += A[i * m + k] * B[k * n + j]; } C[i*n+j] = sum; } } } 2010/09/13 20

プログラム例 : 行列積 (2) void alloc_matrix(float **m_h, float **m_d, int h, int w) { *m_h = (float *)malloc(sizeof(float) * h * w); cudamalloc((void **)m_d, sizeof(float) * h * w); } void init_matrix(float *m, int h, int w) { int i, j; for (i = 0; i < h; i++) for (j = 0; j < w; j++) m[i * w + j] = (float)random(); } 2010/09/13 21

プログラム例 : 行列積 (3) int main(int argc, char *argv[]) { float *Ad, *Bd, *Cd; float *Ah, *Bh, *Ch; // prepare matrix A alloc_matrix(&ah, &Ad, L, M); init_matrix(ah, L, M); cudamemcpy(ad, Ah, sizeof(float) * L * M, cudamemcpyhosttodevice); // do it again for matrix B alloc_matrix(&bh, &Bd, M, N); init_matrix(bh, M, N); cudamemcpy(bd, Bh, sizeof(float) * M * N, cudamemcpyhosttodevice); // allocate spaces for matrix C alloc_matrix(&ch, &Cd, L, N); 2010/09/13 22

プログラム例 : 行列積 (4) // still in function main // launch matmul kernel matmul<<<1, 1>>>(Ad, Bd, Cd, L, M, N); // obtain the result cudamemcpy(ch, Cd, sizeof(float) * L * N, cudamemcpydevicetohost); } return 0; 2010/09/13 23

開発 & コンパイル方法 CUDA プログラムは慣例として.cu の拡張子を使用 コンパイル リンクには CUDA ツールキット付属の nvcc コマンドを利用 ツールキットなどは NVIDIA の CUDA サイトからフリーでダウンロード可能 $ nvcc test.cu o test $./test ( 参考 )nvccの内部動作 1. CUDAプログラムを通常のC++ プログラム部とGPUアセンブリ部 (PTX) へと分割 & 変換 2. C++ コンパイラを呼び出し C++ プログラム部をコンパイルし CUDAライブラリとリンクして実行ファイルを作成 3. GPUアセンブリ部をGPUアセンブリ (ptxas) によってGPU 機械語へコンパイル 2010/09/13 24

実習 先のサンプルプログラム inc_seq.cu をコンパイル 実行し 出力を確認 ソースコードは TSUBAME 上の /work/nmaruyam/gpututorial 以下に有り 手順 $ cd $ cp /work/nmaruyam/gpu-tutorial/gpu-tutorial.zip. $ unzip gpu-tutorial.zip $ cd gpu-tutorial $ cd inc $ nvcc inc_seq.cu o inc_seq $./inc_seq 2010/09/13 25

実習 : SAXPY Y = a X + Y を実装せよ X, Y: 長さ N の float 型配列 サンプルホストコード #include <stdlib.h> #incldue cuda.h #define N (1024) int main(int arc, char *argv[]) { float a = 1.234f; float *x, *y; cudamalloc(&x, sizeof(float)*n); cudamalloc(&y, sizeof(float)*n); saxpy<<<1, 1>>>(x, y, a); return 0; } 2010/09/13 26

SAXPY カーネル関数 global void saxpy(float *x, float *y, float a) { int i; for (i = 0; i < N; i++) { y[i] = a * x[i] + y[i]; } } 2010/09/13 27

ここまでのまとめ C 言語拡張の CUDA の概要 SPMD スタイルの並列性 典型的な CUDA プログラムのパターン GPU 上にデータ領域を確保 (cudamalloc) 確保した GPU 上領域へデータを転送 (cudamemcpy) カーネルを実行 結果を CPU 側メモリへ転送 (cudamemcpy) 用語 ホスト カーネル デバイス デバイスメモリ API( 詳細は CUDA リファレンスマニュアルを参照 ) cudamalloc cudamemcpy 2010/09/13 28

1. CUDA 概要 2. CUDAプログラム例 3. 実行 4. 並列化 5. 同期 6. 最適化 7. 参考資料 目次 2010/09/13 29

並列化 2010/09/13 30

CUDA における並列化 軽量スレッドを用いたマルチスレッド並列化 専用ハードウェアにより数千単位のスレッドの生成 スケジューリングを高速実行 先のプログラム inc_sec.cu は GPU 上で 1 スレッドのみで逐次に実行 データレベル並列性を基にした並列化が一般的 例 : 大規模配列に対して ( ほぼ ) 同一の処理を適用 部分配列への処理に分割し複数スレッドを用いて並列実行 2010/09/13 31

スレッド管理 スレッド全体を階層的にまとめて管理 スレッドブロック 指定した数からなるスレッドの集合 3 次元ベクトルでサイズを指定 グリッド 全スレッドブロックからなる集合 2 次元ベクトルでサイズを指定 スレッド ID スレッドのスレッドブロックと位置 スレッドブロックのグリッド内の位置より決定 Host Kernel 1 Kernel 2 Block (1, 1) (0, 0) (0, 1) (0, 2) Device (1, 0) (1, 1) (1, 2) Grid 1 Block (0, 0) Block (0, 1) Grid 2 (2, 0) (2, 1) (2, 2) Block (1, 0) Block (1, 1) (3, 0) (3, 1) (3, 2) (4, 0) (4, 1) (4, 2) Block (2, 0) Block (2, 1) 2010/09/13 Source: NVIDIA 32

CUDA のマルチスレッド実行 実行コンフィグ (Execution Configuration) ホストプログラムからのカーネル呼び出し時に実行スレッド数を指定 <<< グリッドサイズ (dim3 型または int 型 ), ブロックサイズ (dim3 または int 型 )>>> inc_sec.cu の <<<1, 1>>> ではグリッド ブロックともにサイズ 1 を指定 カーネルが指定されたスレッド数で実行 スレッド間同期 排他制御を一部サポート スレッド ID より各スレッドが計算する部分を決定 2010/09/13 33

グリッド 1 次元または 2 次元でサイズを指定可 整数もしくは dim3 型を指定 ( 整数の場合は 1 次元 ) 以下はすべて等値 : n, dim3(n, 1), dim3(n, 1, 1) カーネル関数から参照可能な組み込み変数 dim3 griddim グリッドサイズ dim3 blockidx グリッド内のブロックのインデックス ( オフセット ) 最大サイズ (TSUBAME) 65535 x 65535 blockidx y Block (0, 0) Block (0, 1) Block (1, 0) Block (1, 1) Block (2, 0) Block (2, 1) griddim: dim3(3, 2) x 2010/09/13 34

スレッドブロック 1 次元 2 次元 3 次元で指定可 カーネル関数から参照可能な組み込み変数 dim3 blockdim ブロックサイズ dim3 threadidx ブロック内のスレッドのインデックス ( オフセット ) 最大サイズの制限有り TSUBAME では 各次元 512 x 512 x 64 全体で 512 blockdim: dim3(5, 3) (0, 0) (0, 1) (0, 2) (1, 0) (1, 1) (1, 2) (2, 0) (2, 1) (2, 2) threadidx (3, 0) (3, 1) (3, 2) (4, 0) (4, 1) (4, 2) 2010/09/13 35 y x

例 :N スレッドを生成 1 ブロック n スレッド生成 グリッドサイズ 1 ブロックサイズ n <<<1, N>>> Block 0 0 1 2 3 4 threadidx.x ただし ブロックあたりのスレッド数に制限有り 仕様上 & ハードウェアリソース上 2010/09/13 36

例 : スレッドインデックスを表示 プログラミングガイドより Fermi 以降でのみ実行可能 コード global void hellocuda() { printf( Hello thread %d n, threadidx.x); } int main(int argc, char *argv[]) { hellocuda<<<1, 5>>>(); return 0; } 出力 Hello thread 0 Hello thread 1 Hello thread 2 Hello thread 3 Hello thread 4 2010/09/13 37

inc の並列化 : バージョン 1 並列化方針 入力 1 次元配列をスレッドで分割 簡単化のためにスレッドブロックは 1 つ ホストプログラム カーネル呼び出し時に実行スレッド構成を指定 32 スレッドの場合 並列版 inc (inc_par.cu) inc<<<1, 32>>>(arrayD, N); 2010/09/13 38

inc の並列化 : バージョン 1 (2) カーネル関数 スレッドインデックスを基に各スレッドのパートを決定 global void inc(int *array, int len) { int i; int tid = threadidx.x; スレッド数 int nthreads = blockdim.x; // assumes len is a multiple of nthreads int part = len / nthreads; for (i = part*tid; i < part*(tid+1); i++) array[i]++; } 2010/09/13 39

inc の並列化 : バージョン 2 バージョン 1 では単純化のために スレッドブロックは 1 つのみ起動 効率はよろしくない ホストプログラム 30 ブロック 32 スレッド起動 inc<<<30, 32>>>(arrayD, N); 2010/09/13 40

inc の並列化 : バージョン 2(2) カーネル関数 バージョン 1 と同様にスレッドインデックスを元に各スレッドの担当パートを決定 ただし バージョン 1 の処理に加えてブロックインデックスを考慮する必要あり global void inc(int *array, int len) { int i; int tid = threadidx.x + blockdim.x * blockidx.x; int nthreads = blockdim.x * griddim.x; // assumes len is a multiple of nthreads int part = len / nthreads; for (i = part*tid; i < part*(tid+1); i++) array[i]++; } 2010/09/13 41

実習 並列版 SAXPY を作成せよ #include <stdlib.h> #incldue cuda.h #define N (1024) int main(int arc, char *argv[]) { float a = 1.234f; float *x, *y; cudamalloc(&x, sizeof(float)*n); cudamalloc(&y, sizeof(float)*n); saxpy<<<1, 512>>>(x, y, a); return 0; } 2010/09/13 42

並列版 SAXPY 1 スレッドあたり N/blockDim 個の要素を担当 global saxpy(float *x, float *y, float a) { int i; int tid = threadidx.x; int tlen = N / blockdim.x; for (i = 0; i < tlen; i++) { y[tid*tlen+i] = a * x[tid*tlen+i] + y[tid*tlen+i]; } } 2010/09/13 43

並列 SAXPY 複数ブロック版 #include <stdlib.h> #incldue cuda.h #define N (1024) int main(int arc, char *argv[]) { float a = 1.234f; float *x, *y; cudamalloc(&x, sizeof(float)*n); cudamalloc(&y, sizeof(float)*n); saxpy<<<n/512, 512>>>(x, y, a); return 0; } 2010/09/13 44

並列 SAXPY 複数ブロック版カーネル 1 スレッドあたり 1 個の要素を担当 global saxpy(float *x, float *y, float a) { int i; int tid = threadidx.x + blockdim.x*blockidx.x; y[tid+i] = a * x[tid*tlen+i] + y[tid*tlen+i]; } 2010/09/13 45

方針 並列化その 2: 行列積 結果の行列 C の各要素の計算はデータ並列 それぞれ別個のスレッドで計算し並列化 行列は 2 次元 スレッドを 2 次元行列にマッピング Matrix C j i 各スレッドが 1 要素を計算 2010/09/13 46

並列行列積バージョン 1 スレッドの構成 2 次元のスレッドブロックにスレッドを割り当て 1 スレッドが行列 C の 1 要素を計算 C の要素 (threadidx.x, threadidx.y) を計算 単純化のためにブロックは 1 つのみ使用 ( バージョン 2 で拡張 ) 例 : l = m = 16 の場合 matmul<<<1, dim3(16,16)>>>(ad, Bd, Cd, L, M, N); カーネルの構成 各カーネルは内積を 1 回のみ計算 2010/09/13 47

threadidx.y 並列行列積 : バージョン 1 逐次版からの変更点 カーネル呼び出し ( ヒントの通り ) カーネル関数 行列 C の LxN 要素を LxN スレッドで等分割 各スレッドが行列 C の 1 要素 (C[i][j]) のみを計算 スレッドの計算対象要素 スレッドブロック内の位置 i: threadidx.y, j: threadidx.x block threadidx.x Matrix C j (0, 0) (1, 0) (2, 0) (3, 0) (4, 0) (0, 1) (1, 1) (2, 1) (3, 1) (4, 1) i (0, 2) (1, 2) (2, 2) (3, 2) (4, 2) 2010/09/13 48

並列行列積 : バージョン 1 プログラムリスト : matmul_par.cu i j global void matmul(float *A, float *B, float *C, int l, int m, int n) { int i, j, k; i = threadidx.y; j = threadidx.x; float sum = 0.0; for (k = 0; k < m; k++) { sum += A[i*m+k] * B[k*n+j]; } C[i*n+j] = sum; } 2010/09/13 49

並列行列積 : バージョン 2 より大きなサイズの行列への対応 初めの設計 16x16 のスレッドブロック 1 つを立ち上げ 各スレッドが内積を 1 要素分計算 16x16 以上のサイズの行列は? スレッドブロックを大きくすれば良い? No! 1 ブロックにつき最大スレッド数は 512 (Tesla T10) (32x32 1024 スレッド必要 ) 複数ブロックを使うことで対応 2010/09/13 50

並列行列積 : バージョン 2 各スレッドは今回も行列 C の 1 要素の内積を計算 16x16 のスレッドブロックを複数立ち上げ 各スレッドブロックが行列 C の部分行列を担当 先頭要素からのオフセット x: blockidx.x * blockdim.x y: blockidx.y * blockdim.y blockidx.x blockdim.x blockidx.y blockdim.y 先頭要素からのオフセット x: blockidx.x * blockdim.x + threadidx.x y: blockidx.y * blockdim.y + threadidx.y Matrix C 2010/09/13 51

並列行列積 : バージョン 2 プログラムリ スト (1) プログラムリスト : matmul_mb.cu より抜粋 #define BLOCKSIZE (16) #define L (BLOCKSIZE * 16) #define M (BLOCKSIZE * 16) #define N (BLOCKSIZE * 16) 16x16 スレッド数のブロックを立ち上げ 縦横 16 倍の行列を計算 16x16 ブロック数のグリッドを立ち上げ global void matmul(float *A, float *B, float *C, int l, int m, int n) { int i, j, k; float sum; i = blockidx.y * blockdim.y + threadidx.y; j = blockidx.x * blockdim.x + threadidx.x; 複数ブロックへの対応 } sum = 0.0; for (k = 0; k < m; k++) { sum += A[i * m + k] * B[k * n + j]; } C[i*n+j] = sum; 2010/09/13 52

並列行列積 : バージョン 2 プログラムリ int main(int argc, char *argv[]) { float *Ad, *Bd, *Cd; float *Ah, *Bh, *Ch; struct timeval t1, t2; } スト (2) // prepare matrix A alloc_matrix(&ah, &Ad, L, M); init_matrix(ah, L, M); cudamemcpy(ad, Ah, sizeof(float) * L * M, cudamemcpyhosttodevice); // do it again for matrix B alloc_matrix(&bh, &Bd, M, N); init_matrix(bh, M, N); cudamemcpy(bd, Bh, sizeof(float) * M * N, cudamemcpyhosttodevice); // allocate spaces for matrix C alloc_matrix(&ch, &Cd, L, N); // launch matmul kernel matmul<<<dim3(n / BLOCKSIZE, L / BLOCKSIZE), dim3(blocksize, BLOCKSIZE)>>>(Ad, Bd, Cd, L, M, N); return 0; プログラムリスト : matmul_mb.cu より抜粋 複数ブロックの立ち上げ 2010/09/13 53

ここまでのまとめ 階層化されたスレッド構成を用いたマルチスレッド並列化 スレッドブロック Host Kernel 1 Device Grid 1 Block (0, 0) Block (0, 1) Block (1, 0) Block (1, 1) Block (2, 0) Block (2, 1) グリッド Kernel 2 Grid 2 Block (1, 1) (0, 0) (1, 0) (2, 0) (3, 0) (4, 0) (0, 1) (1, 1) (2, 1) (3, 1) (4, 1) 2010/09/13 54 (0, 2) (1, 2) (2, 2) (3, 2) (4, 2)

最適化 2010/09/13 55

最適化基本方針 メモリアクセス効率化 オンチップメモリの有効活用 共有メモリ ハードウェアキャッシュ (Fermi 以降 ) 連続領域へのアクセスによるメモリアクセスの一括処理 共有メモリへのバンクコンフリクトの削減 計算処理効率化 divergent 分岐の削除 ホスト デバイス間データ転送 ハードウェアの詳細を ( それなりに ) 知る必要有り ただし 最適化による効果も大きい 2010/09/13 56

CUDA メモリモデル 階層化スレッドグルーピングと同様に階層化されたメモリモデルを提供 スレッド固有 レジスタ ローカルメモリ ブロック内共有 共有メモリ グリッド内 ( 全スレッド ) 共有 グローバルメモリ コンスタントメモリ テクスチャメモリ ないもの スタック それぞれ速度と容量にトレードオフ有 ( 高速 & 小容量 vs. 低速 & 大容量 ) メモリアクセスの局所性が重要 Host (Device) Grid Block (0, 0) Registers Local Memory Global Memory Constant Memory Texture Memory Shared Memory (0, 0) Registers (1, 0) Local Memory Block (1, 0) Registers Local Memory Shared Memory (0, 0) Registers (1, 0) Local Memory 2010/09/13 57 Source: Kirk and Hwu, ECE 498AL, UIUC

スレッド固有メモリ レジスタ GPU チップ内に実装 (i.e., オンチップメモリ ) カーネル関数のローカル変数を保持 高速 ( 遅延無しで計算ユニットより利用可 ) T10 ではブロックあたり 16384 本 スレッドでレジスタ領域を等分割して利用 ローカルメモリ GPU チップ外のデバイスメモリに配置 (i.e., オフチップメモリ ) レジスタへ一度ロードしてからのみ利用可能 主にローカル変数の退避領域として利用 非常に低速 (400-600 サイクル ) Block (0, 0) Registers Local Memory Shared Memory (0, 0) Registers (1, 0) Local Memory 2010/09/13 58

ブロック内共有メモリ 共有メモリ (shared memory) ブロック内スレッドのみで 共有 スレッド全体で共有されるわけではない オンチップメモリ レジスタに次いで高速 SMあたり16KBもしくは48KB(Fermi) Block (0, 0) Registers Local Memory Shared Memory (0, 0) Registers (1, 0) Local Memory 2010/09/13 59

Fermi GPU より搭載 128B キャッシュライン L1 キャッシュ 共有メモリと物理的に同じ領域に存在 SM あたり 16KB もしくは 48KB( 選択可 ) cudafuncsetcacheconfig() 関数により設定 例 : cudafuncsetcacheconfig(inc1, cudafunccachepreferl1) 2010/09/13 60

グリッド内 ( 全スレッド ) 共有メモリ GPU チップ外に実装 ( オフチップ ) グローバルメモリ T10 で 4GB 低速 (400-600 サイクル ) コンスタントメモリ ホスト側からのみ読み書き可能 カーネル側からは読み込みのみ可能 この授業では扱わない テクスチャメモリ この授業では扱わない (Device) Grid Block (0, 0) Registers Global Memory Shared Memory (0, 0) Local Memory Registers (1, 0) Local Memory Block (1, 0) Registers Shared Memory (0, 0) Local Memory Registers (1, 0) Local Memory Constant Memory Texture Memory 2010/09/13 61

Fermi より搭載 C2050 で 768KB 128B キャッシュライン 全 SM より共有 L2 キャッシュ アトミック操作などの実装にも利用 Fermi 以前と比べて性能向上 2010/09/13 62

共有メモリを用いた最適化 キャッシュのついた Fermi 以降では性能悪化の場合もあり ( ステンシルなど ) 2010/09/13 63

グローバルメモリアクセスの最適化 グローバルメモリへのアクセス 例 : inc における配列アクセス matmul における行列アクセス 現世代までの GPU ではハードウェアキャッシュ無し 次世代 GPU(Fermi) からは L1/L2 データキャッシュ有り CUDA プログラムにおける最も大きなボトルネックのひとつ 最適化 : オンチップメモリをキャッシュとして活用 (Software-managed cache) プログラムの局所性を特定し オンチップメモリをプログラマが明示的にキャッシュとして活用 グローバルメモリへのアクセスを削減 2010/09/13 64

CUDA における局所性 時間的局所性 同一スレッドが同一データに複数回アクセス 例 : 初回にオンチップ領域に読み込み オンチップ領域を用いて計算 最後にグローバルメモリへ書き込み レジスタを利用 スレッド間局所性 異なるスレッド間で同じデータへアクセス 例 : あるスレッドが読み込んだデータを他のスレッドからも利用 スレッド間で共有可能なオンチップメモリを利用 共有メモリ 2010/09/13 65

共有メモリによる最適化 スレッドブロック内スレッドで共有可能 典型的な利用パターン 1. 各スレッドがグローバルメモリよりデータを読み込み 2. スレッドブロック内スレッドで同期をとり 読み込みを完了 syncthreads 組み込み関数を使用 3. 各スレッドが自身で読み込んだデータと他のスレッドが読み込んだデータを使って計算 2010/09/13 66

共有メモリの同期 スレッドブロック内の同期 syncthreads 拡張命令を利用 この命令を呼ぶまでは 共有メモリに書いた値が必ずしも他のスレッドへ反映されない 2010/09/13 67

共有メモリを用いた行列積の最適化 タイリング 1. 行列 A B 共に共有メモリに収まるサイズの部分行列 ( タイル ) を共有メモリに読み込み 2. 共有メモリを用いて部分行列のかけ算 3. 次のタイルの積を計算 4. 繰り返し 2010/09/13 68

ブロックの読み込み 最適化前 スレッド t i, t i+1 はそれぞれ同一行をロード 最適化後 スレッド ti, ti+1 はそれぞれ 1 要素のみをロード 内積計算は共有メモリ上の値を利用 16x16 の場合 1/16 に読み込みを削減 t i t i+1 block block 共有メモリ グローバルメモリ 2010/09/13 69

行列積 ( 共有メモリ版 ) CUDA Programming Guide, Chapter 6 より global void Muld(float* A, float* B, int wa, int wb, float* C) { // Block index int bx = blockidx.x; int by = blockidx.y; // index int tx = threadidx.x; int ty = threadidx.y; // Index of the first sub-matrix of A // processed by the block int abegin = wa * BLOCK_SIZE * by; // Index of the last sub-matrix of A // processed by the block int aend = abegin + wa - 1; 2010/09/13 70

行列積 ( 共有メモリ版 ) // Step size used to iterate through // the sub-matrices of A int astep = BLOCK_SIZE; // Index of the first sub-matrix of B // processed by the block int bbegin = BLOCK_SIZE * bx; // Step size used to iterate through the // sub-matrices of B int bstep = BLOCK_SIZE * wb; // The element of the block sub-matrix // that is computed by the thread float Csub = 0; 2010/09/13 71

行列積 ( 共有メモリ版 ) // Loop over all the sub-matrices of A and B // required to compute the block sub-matrix for (int a = abegin, b = bbegin; a <= aend; a += astep, b += bstep) { // Shared memory for the sub-matrix of A shared float As[BLOCK_SIZE][BLOCK_SIZE]; // Shared memory for the sub-matrix of B shared float Bs[BLOCK_SIZE][BLOCK_SIZE]; // Load the matrices from global memory to // shared memory; // each thread loads one element of each matrix As[ty][tx] = A[a + wa * ty + tx]; Bs[ty][tx] = B[b + wb * ty + tx]; // Synchronize to make sure the matrices are loaded syncthreads(); 2010/09/13 72

行列積 ( 共有メモリ版 ) // Multiply the two matrices together; // each thread computes one element // of the block sub-matrix for (int k = 0; k < BLOCK_SIZE; ++k) Csub += As[ty][k] * Bs[k][tx]; // Synchronize to make sure that the preceding // computation is done before loading two new // sub-matrices of A and B in the next iteration syncthreads(); } // Write the block sub-matrix to global memory; // each thread writes one element int c = wb * BLOCK_SIZE * by + BLOCK_SIZE * bx; C[c + wb * ty + tx] = Csub; } 2010/09/13 73

GFLOPS matmul_mb.cu 共有メモリは使用せず matmul_shared.cu 最適化の効果 共有メモリを用いた並列行列積 TSUBAME の GPU での計測結果 250 200 150 100 Non-Opt Opt 50 0 512x512 1024x1024 2010/09/13 74

グローバルメモリアクセスの一 括処理 ( コアレッシング ) 2010/09/13 75

コアレッシング グラフィックスメモリは連続アドレスへのバーストアクセスに最適化 Tesla C10 で理論値 100GB/s ランダムアクセスに弱い ただし Fermi 以降では L1/L2 キャッシュにより改善 メモリアクセスのコアレッシング (coalescing) 複数スレッドのメモリアクセスを一括 ( 並列 ) 処理 CUDA ではハーフワープ毎にコアレッシング 2010/09/13 76

コアレッシングされる条件 (Tesla T10) ハーフワープの各スレッドが同一データサイズにアクセスする場合 8 ビット 16 ビット 32 ビット 64 ビット かつ それぞれアクセスする先が一定サイズのセグメント内に収まる場合 8 ビット 32 バイト, 16 ビット 64 バイト 32 ビット 128 バイト 64 ビット 128 バイト その他アラインメントの制限もあり 古い世代の GPU ではさらに制限あり 詳細は CUDA Programming Guide 2.0, Section 5.1.2.1 を参照 Compute capability 1.2 の場合を参照 2010/09/13 77

コアレッシング例その 1 CUDA Programming Guide 2.0, Fig. 5.1 2010/09/13 78

共有メモリのバンクと バンクコンフリクト 注 : 一部の図 文はUIUC ECE498より抜粋 (http://courses.ece.uiuc.edu/ece498/al/syllabus.html) 2010/09/13 80

メモリバンク GPU のようなマルチスレッドアーキテクチャでは複数スレッドが同時にメモリにアクセス メモリが一度に 1 アクセスしか処理できない場合 逐次処理に ボトルネックになりがち 共有メモリではメモリを複数バンクに分割 各バンクは連続した 32 ビット毎のアドレスに対応 Fermi 以前の GPU では 16 バンク Fermi GPU では 32 バンク 16 スレッドもしくは 32 スレッドが別個のアドレスにアクセス 全バンクを使うことにより並列処理 複数スレッドが同一アドレスにアクセス アクセス先バンクの衝突 ( バンクコンフリクト ) Bank 0 Bank 1 Bank 2 Bank 3 Bank 4 Bank 5 Bank 6 Bank 7 Bank 15 2010/09/13 81

バンクコンフリクトが起きない例 No Bank Conflicts 0 1 2 3 4 5 6 7 Linear addressing stride == 1 Bank 0 Bank 1 Bank 2 Bank 3 Bank 4 Bank 5 Bank 6 Bank 7 No Bank Conflicts 0 1 2 3 4 5 6 7 Random 1:1 Permutation Bank 0 Bank 1 Bank 2 Bank 3 Bank 4 Bank 5 Bank 6 Bank 7 15 Bank 15 15 Bank 15 2010/09/13 82

バンクコンフリクトが起きる例 2-way Bank Conflicts 0 1 2 3 4 8 9 10 11 Linear addressing stride == 2 Bank 0 Bank 1 Bank 2 Bank 3 Bank 4 Bank 5 Bank 6 Bank 7 Bank 15 8-way Bank Conflicts 0 1 2 3 4 5 6 7 15 Linear addressing stride == 8 x8 x8 Bank 0 Bank 1 Bank 2 Bank 7 Bank 8 Bank 9 Bank 15 2010/09/13 83

ライブラリ等 2010/09/13 84

CUDA SDK の利用方法 サンプルコード 補助ライブラリなどを含む http://www.nvidia.com/object/cuda_get.html より最新版はダウンロード可能 TSUBAME ではバージョンは 2.3 を利用 TSUBAME の本講習用ディレクトリ以下にある NVIDIA_CUDA_SDK_*.run という名前のファイル ファイルの展開 sh < ダウンロードしたファイル名 > Enter 連打 コンパイル 展開されたディレクトリへ移動 make 2010/09/13 85

CUTIL ライブラリ CUDA SDK について 各種補助関数 マクロを提供 例 CUDA_SAFE_CALL(call) call を実行後 同期 & エラーチェック SDK_DIR/common 以下にプログラムファイル有り projects 以下のサンプルコードで使用 CUTIL を利用したサンプルコードをベースにプログラムを構成する場合は CUTIL 関連のファイルへの依存性に注意 ヘッダーファイルの場所の指定 -ISDK_DIR/common/inc ライブラリの指定 LSDK_DIR/common/lib -lcutil 2010/09/13 86

CUBLAS 単精度 : Level 1, 2, 3 すべて 倍精度 Level 1: DASUM, DAXPY, DCOPY, DDOT, DNRM2, DROT, DROTM, DSCAL, DSWAP, ISAMAX, IDAMIN Level 2: DGEMV, DGER, DSYR, DTRSV Level 3: ZGEMM, DGEMM, DTRSM, DTRMM, DSYMM, DSYRK, DSYR2K 行列のデータ順 Column major (BLAS と同じ ) 2010/09/13 87

CUBLAS 利用法 cublas.h のインクルード simplecublas.c より抜粋 #include cublas.h cublas の初期化 GPU メモリに配列を確保 配列に入力データをセット int main(int argc, char *argv[]) { status = cublasinit(); if (status!= CUBLAS_STATUS_SUCCESS) { fprintf (stderr, "!!!! CUBLAS initialization error n"); return EXIT_FAILURE; } status = cublasalloc(n2, sizeof(d_a[0]), (void**)&d_a); if (status!= CUBLAS_STATUS_SUCCESS) { fprintf (stderr, "!!!! device memory allocation error (A) n"); return EXIT_FAILURE; } /* Initialize the device matrices with the host matrices */ status = cublassetvector(n2, sizeof(h_a[0]), h_a, 1, d_a, 1); if (status!= CUBLAS_STATUS_SUCCESS) { fprintf (stderr, "!!!! device access error (write A) n"); return EXIT_FAILURE; } 2010/09/13 88

CUBLAS 利用法 BLAS ルーチンを呼び出し 結果を CPU 側メモリへ転送 simplecubla.c より抜粋 /* Performs operation using cublas */ cublassgemm('n', 'n', N, N, N, alpha, d_a, N, d_b, N, beta, d_c, N); status = cublasgeterror(); if (status!= CUBLAS_STATUS_SUCCESS) { fprintf (stderr, "!!!! kernel execution error. n"); return EXIT_FAILURE; } h_c = (float*)malloc(n2 * sizeof(h_c[0])); if (h_c == 0) { fprintf (stderr, "!!!! host memory allocation error (C) n"); return EXIT_FAILURE; } /* Read the result back */ status = cublasgetvector(n2, sizeof(h_c[0]), d_c, 1, h_c, 1); if (status!= CUBLAS_STATUS_SUCCESS) { fprintf (stderr, "!!!! device access error (read C) n"); return EXIT_FAILURE; } } コンパイル $ gcc simplecublas.c I/opt/cuda/include -L/opt/cuda/lib -lcublas 2010/09/13 89

CUBLAS の Fortran からの利用法 方法 1: C 言語版 CUDA で GPU プログラムを書き Fortran から呼び出し GSIC Tesla 利用の手引き 5 章を参照してください http://www.gsic.titech.ac.jp/~ccwww/tebiki/tesla/tes la5.html 方法 2: すべて Fortran で記述 PGI 社のコンパイラに CUDA for Fotran の開発キットが付属 2010/09/13 90

CUFFT FFTW をモデルに構成 1. はじめにプランを作成しデータサイズ GPU に最適化するためのデータを作成 2. プランを用いて ( 複数回 )FFT を実行 実数 & 複素数の 1D, 2D, 3D FFT をサポート 2D と 3D では配列内データ配置は rowmajor Fortran から使う場合は転置する必要有り 2010/09/13 91

CUFFT サンプルコード #include cufft.h #define NX 256 #define NY 128 cuffthandle plan; cufftcomplex *idata, *odata; cudamalloc((void**)&idata, sizeof(cufftcomplex)*nx*ny); cudamalloc((void**)&odata, sizeof(cufftcomplex)*nx*ny); /* Create a 1D FFT plan. */ cufftplan2d(&plan, NX,NY, CUFFT_C2C); /* Use the CUFFT plan to transform the signal out of place. */ cufftexecc2c(plan, idata, odata, CUFFT_FORWARD); /* Inverse transform the signal in place. */ cufftexecc2c(plan, odata, odata, CUFFT_INVERSE); /* Note: Different pointers to input and output arrays implies out of place transformation */ /* Destroy the CUFFT plan. */ cufftdestroy(plan); cudafree(idata), cudafree(odata); 2010/09/13 92 Source: Massimilaino Fatica, CUDA Toolkit, CUDA Tutorial at SC 08.

LAPACK CULA by CULAtools http://www.culatools.com/ 無料版と有料版があり 無料版は単精度の一部ルーチンのみ 有料版はほぼすべてルーチンをカバー ( 倍精度含む ) MAGMA by テネシー大 http://icl.cs.utk.edu/magma/ フリー 2010/09/13 93

補足 2010/09/13 94

デバイス情報の参照 SDK 付属の devicequery を利用 projects/devicequery 以下にソース bin/linux/release/devicequeryが実行バイナリ /work/nmaruyam/gpu-tutorial 以下にもあり 例 tgg075055:~$ /work/gpu/maruyama/devicequery There are 4 devices supporting CUDA Device 0: "Tesla T10 Processor" Major revision number: 1 Minor revision number: 3 Total amount of global memory: 4294705152 bytes Number of multiprocessors: 30 Number of cores: 240 Total amount of constant memory: 65536 bytes Total amount of shared memory per block: 16384 bytes Total number of registers available per block: 16384 Warp size: 32 Maximum number of threads per block: 512 Maximum sizes of each dimension of a block: 512 x 512 x 64 Maximum sizes of each dimension of a grid: 65535 x 65535 x 1 Maximum memory pitch: 262144 bytes Texture alignment: 256 bytes Clock rate: 1.44 GHz Concurrent copy and execution: Yes 2010/09/13 95

Fortran からの GPU の利用 方法 1: GPU 部分は CUDA C で記述 Fortran から C の関数を呼び出し GPU を利用 方法 2: CUDA Fortran を使い Fortran から直接 CUDA プログラムを記述 CUDA Fortran を用いた GPU コンピューティング http://www.gsic.titech.ac.jp/~ccwww/tebiki/tesl a/pgi_cuda_fortran.html 第 4 回講習会資料 http://gpucomputing.gsic.titech.ac.jp/japanese/lecture/ 2010-03-19/index.html 2010/09/13 96

最適化効果の測定 カーネル実行時間を計測 カーネル実行前後に gettimeofday 関数呼び出しを挿入 但し 適切に同期させる必要あり カーネル実行は非同期 メモリ転送も非同期可 cudasynchronize 呼び出し時点までに呼び出したデバイス関連の実行の終了をすべて待つ 2010/09/13 97

時間計測例 プログラムリスト : matmul_mb.cu より抜粋 cudasynchronize(); 非同期実行の処理の完了を待ち gettimeofday(&t1, NULL); // launch matmul kernel matmul<<<dim3(n / BLOCKSIZE, L / BLOCKSIZE), dim3(blocksize, BLOCKSIZE)>>>(Ad, Bd, Cd, L, M, N); cudasynchronize(); 非同期実行の処理の完了を待ち gettimeofday(&t2, NULL); printf("elapsed time: %f n", get_elapsed_time(&t1, &t2)); 2010/09/13 98

デバッグ cuda-memcheck コマンド 領域外アクセスの検出 CUDA 3.0 より cuda-gdb デバッガ CUDA_SAFE_CALL CUDA API 呼び出しのエラーチェック用マクロ SDK の CUTIL に定義 SDK 内サンプルプログラムで利用 CUDA v2 まではエミュレーションも可 v3 よりサポート外 ( 非推奨 ) 2010/09/13 99

その他取り上げられなかった事項 メモリ テクスチャメモリ ローカルメモリ コンスタントメモリ 動的にサイズが決まる共有メモリの割り当て アトミック操作 ホストと GPU 間のデータ転送の最適化 エラー処理 デバッガ Linux 64-bit 用にはハードウェアデバッガ有り (TSUBAME では未提供 ) Windows 向けには VisualStudio プラグインとして Nexus が提供予定 プロファイラ 環境変数の設定により GPU 上のパフォーマンスカウンタ値をファイルへ保存 CUDPP http://gpgpu.org/developer/cudpp CUDA SDK に付属 scan, reduction などのプリミティブをライブラリとして提供 2010/09/13 100

NVIDIA CUDA サイト 参考資料 http://www.nvidia.com/object/cuda_develop.html CUDA Reference Manual & Programming Guide 上記サイトよりダウンロード可能 Fermi Tuning Guide http://developer.download.nvidia.com/comput e/cuda/3_1/toolkit/docs/nvidia_fermituning Guide.pdf GSIC, Tesla 利用の手引き 2010/09/13 101