gpgpu seminar (gpu accelerated libraries, 1 of 3, cublas)

81
GPGPU講習会 GPU最適化ライブラリの利用(その1) 長岡技術科学大学電気電子情報工学専攻 出川智啓

Upload: -

Post on 16-Apr-2017

251 views

Category:

Engineering


11 download

TRANSCRIPT

Page 1: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

GPGPU講習会GPU最適化ライブラリの利用(その1)

長岡技術科学大学電気電子情報工学専攻 出川智啓

Page 2: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

本講習会の目標

GPGPU先端シミュレーションシステムの使用方法の習得

GPUの活用方法の修得

CUDAプログラミング技法の修得

並列計算手法の修得

2015/10/14GPGPU講習会2

Page 3: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

本日の内容

GPU最適化ライブラリの利用(その1)

GPU最適化ライブラリの紹介

共役勾配法(およびKrylov部分空間法)

cuBLASの紹介

cuBLASによる共役勾配法の実装

連立一次方程式を解くプログラムの作成

ライブラリを利用

関数(およびCUDA API)の呼出のみで作成

3回に分けて徐々に効率化

2015/10/14GPGPU講習会3

Page 4: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

GPU最適化ライブラリ

Page 5: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

ライブラリ

2015/10/14GPGPU講習会5

特定の処理を行う複数のプログラムを再利用可能な形でまとめた集合体

動画像処理やファイル圧縮,数値計算などが有名

自作のプログラムよりも性能が高いため,関数を置き換えるだけで処理速度の向上に貢献

Page 6: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

数値計算ライブラリ

2015/10/14GPGPU講習会6

FFT(Fast Fourier Transform) FFTW

線形代数演算(ベクトル処理,行列処理)

BLAS(Basic Linear Algebra Subprogram)

BLASを利用した線形代数演算ライブラリ LAPACK LINPACK ScaLAPACK

BLASやLAPACKのメーカー別実装 MKL  Intel Math Kernel Library ACML AMD Core Math Library IMSL International Mathematics and Statistics Library

Page 7: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

CUDA付属のライブラリ

2015/10/14GPGPU講習会7

cuBLAS 密行列向け線形代数演算

cuSPARSE 疎行列向け線形代数演算

cuFFT フーリエ変換

cuRAND 乱数生成

Thrust ソート,縮約,スキャン等

NPP 画像処理,信号処理

など

NVIDIAホームページに一覧がある

https://developer.nvidia.com/gpu‐accelerated‐libraries

Page 8: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

その他GPU向けライブラリ

2015/10/14GPGPU講習会8

cuDNN https://developer.nvidia.com/cudnn

Deep Neural Network用のライブラリ

機械学習用のフレームワークをサポート

Caffe Theano Torch

cuDNNを使ったDIGITSというシステムを利用してNeural Networkのトレーニングを行うことが可能

Page 9: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

その他GPU向けライブラリ

2015/10/14GPGPU講習会9

MAGMA http://icl.cs.utk.edu/magma/

NVIDIA GPU向けの線形代数ライブラリ

CPUも同時に使うハイブリッド型のライブラリであるため,GPU単体より高速

BLAS, LAPACKに準ずるような形で関数形が定められている

cuBLASに取り込まれている関数もある

ソースコードが配布されており,無料で入手できる

Page 10: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

その他GPU向けライブラリ

2015/10/14GPGPU講習会10

cuBLAS‐XT https://developer.nvidia.com/cublasxt

cuBLASライブラリのマルチGPU向け実装

CUDA 6.0, 6.5から利用可能

Page 11: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

共役勾配法

Page 12: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

数値シミュレーションと連立一次方程式

2015/10/14GPGPU講習会12

数値シミュレーション

自然現象を記述する偏微分方程式の解を求める

微積分を計算機で形に変換(離散化)

離散化方法

有限差分法

空間に飛び飛びの点(離散点)を配置し,その点上で物理量を定義

微分を差分に置き換え,離散点での物理量を使って微分を計算

有限要素法

空間を要素と呼ばれる微小な空間に分割

要素内での物理量変化を基底関数で定義し,空間全体の物理量変化を基底関数の結合として表現

Page 13: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

数値シミュレーションと連立一次方程式

2015/10/14GPGPU講習会13

空間の平衡状態の計算

水・空気中の圧力分布

物体中の温度分布

金属材料が受ける応力分布

逆問題

物理量が従う式だけが分かっていて,物理量の値が不明

Laplace/Poisson方程式

?2

2

2

2

yf

xf

f 02

2

2

2

yf

xf

?f

逆問題順問題

Page 14: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

数値シミュレーションと連立一次方程式

2015/10/14GPGPU講習会14

空間の平衡状態の計算

水・空気中の圧力分布

物体中の温度分布

金属材料が受ける応力分布

逆問題

物理量が従う式だけが分かっていて,物理量の値が不明

ある点での値の変化が他の点にも影響

連立一次方程式を作成して全点の値を同時に求める

方程式を解く時間が数値シミュレーションの大半を占める

シミュレーションの規模が大きくなると連立一次方程式の規模も大きくなる

Page 15: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

連立一次方程式の解法

2015/10/14GPGPU講習会15

直接法

係数行列を単位行列(や上三角,下三角行列)に変形することで未知数を求める方法

所定の計算回数で解が得られる

計算量が多く,大規模な問題には適用が難しい

反復法

係数行列を変更せず,未知数に推定値を代入して所定の計算を行い,推定値が解に十分近づくまで計算を繰り返す方法

よい推定値を選べば非常に高速に解が得られる

Page 16: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

共役勾配法

2015/10/14GPGPU講習会16

連立一次方程式を解くためのアルゴリズム

係数行列が対称・正定値である連立一次方程式が対象

Hestenes and Stiefel(1952)によって提案

反復解法の性質を持ちながら,直接解法のように有限回の計算で解が得られる

「世紀の大解法」ともてはやされた

丸め誤差に弱く,有限回の計算で終わらないこともある

Hestenes, Magnus R., Stiefel, Eduard (December, 1952). "Methods of Conjugate Gradients for Solving Linear Systems". Journal of Research of the National Bureau of Standards 49 (6).

Page 17: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

共役勾配法のアルゴリズム

2015/10/14GPGPU講習会17

連立一次方程式Ax=bに対する共役勾配法

Ap 係数行列Aとベクトルpの積

( , ) ベクトル同士の内積

Compute r(0)=b−Ax(0). Set p(0)=0,c2(0)=0.

For k=1,…, until ||r||/||b|| < , Do

p(k) = r(k)+c2(k−1)p(k−1)

c1(k) = (r(k), r(k))/(p(k), Ap(k))

x(k+1) = x(k)+c1(k)p(k)

r(k+1) = r(k)−c1(k)Ap(k)

c2(k) = (r(k+1), r(k+1))/{c1

(k)(p(k), Ap(k))}

EndDo

A 係数行列x 解ベクトルb 右辺ベクトルr 残差ベクトルp 補助ベクトル||・|| l2−ノルム

Page 18: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

共役勾配法のバリエーション

2015/10/14GPGPU講習会18

自乗共役勾配法(CGS法)

非対称行列に対応

Compute r(0)=b−Ax(0). Set p(0)=0,c2(0)=0, r*=r(0).

For k=1,…, until ||r||/||b|| < , Dop(k) = r(k)+c2

(k−1)z(k−1)

u(k) = p(k)+c2(k−1)(z(k−1)+c2

(k−1)u(k−1))c1

(k) = (r*, r(k))/(r*, Au(k))z(k) = p(k)−c1

(k)Au(k)

x(k+1) = x(k)+c1(k)(p(k)+z(k))

r(k+1) = r(k)−c1(k)A(p(k)+z(k))

c2(k) = (r*, r(k+1))/{c1

(k)(r*, Au(k))}EndDo

r* 疑似残差u 補助ベクトルz 補助ベクトル

Page 19: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

共役勾配法のバリエーション

2015/10/14GPGPU講習会19

安定化双共役勾配法(Bi‐CGSTAB法)

非対称行列に対応

Compute r(0)=b−Ax(0). Set p(0)=0,c2(0)=0, r*=r(0).

For k=1,…, until ||r||/||b|| < , Dop(k) = r(k)+c2

(k−1)(p(k−1)−c3(k−1)Ap(k−1))

c1(k) = (r*, r(k))/(r*, Ap(k))t(k) = r(k)−c1

(k)Ap(k)

c3(k) = (At(k), t(k))/(At(k), At(k))x(k+1) = x(k)+c1

(k)p(k)+c3(k)t(k)

r(k+1) = r(k)−c3(k)At(k)

c2(k) = (r*, r(k+1))/{c3

(k)(r*, Ap(k))}EndDo

r* 疑似残差t 補助ベクトル

Page 20: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

連立一次方程式

2015/10/14GPGPU講習会20

3重対角行列

2次元Poisson方程式から導かれる係数行列を簡略化

解(x)が0, 1, 2・・・N−1となるようbを設定

N

N

N

N

bb

bb

xx

xx

1

2

1

1

2

1

41141

14114

0

0

Page 21: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

CPUプログラム(制御部分)

2015/10/14GPGPU講習会21

#include<stdlib.h>#include<stdio.h>#include<math.h>int main(void){

int N = 1 << 10;          //未知数の数210const double err_tol = 1e‐9; //許容誤差const int max_ite = 1<<20;//反復回数の上限

double *x; //近似解ベクトルdouble *b; //右辺ベクトルdouble *A; //係数行列double *sol; //厳密解double *r, rr; //残差ベクトル, 残差の内積double *p, *Ax; //補助ベクトル,行列ベクトル積double c1, c2, dot; //計算に使う係数int i, k;//メモリの確保A = (double *)malloc(sizeof(double)*N*N);x = (double *)malloc(sizeof(double)*N);b = (double *)malloc(sizeof(double)*N);sol= (double *)malloc(sizeof(double)*N);r  = (double *)malloc(sizeof(double)*N);p  = (double *)malloc(sizeof(double)*N);

Ax = (double *)malloc(sizeof(double)*N);

for (i = 0; i < N; i++){sol[i] = (double)i; //厳密解を設定

x[i] = 0.0;       //近似解を0で初期化}//係数行列Aの生成setTridiagonalMatrix(A, N);//右辺ベクトルbの生成setRightHandSideVector(b, A, sol, N);//        :// ここで共役勾配法を実行//        ://確保したメモリを解放free(x);free(b);free(A);free(sol);free(r);free(p);free(Ax);

} cg_cpu.c

Page 22: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

CPUプログラム(係数行列の生成)

2015/10/14GPGPU講習会22

void setTridiagonalMatrix(double *A, int N){int i,j;

for (j = 0; j < N; j++){for (i = 0; i < N; i++){

A[i+N*j] = 0.0;}

}

i = 0;A[i + N*i  ] = ‐4.0;A[i + N*i+1] =  1.0;

for(i = 1; i < N‐1; i++){A[i + N*i‐1] =  1.0;A[i + N*i  ] = ‐4.0;A[i + N*i+1] =  1.0;

}i = N‐1;

A[i + N*i‐1] =  1.0;A[i + N*i  ] = ‐4.0;

}

41141

14114

cg_cpu.c

i

j

Page 23: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

CPUプログラム(右辺ベクトルの生成)

2015/10/14GPGPU講習会23

void setRightHandSideVector(double *b, double *A, double *x, int N){

int i,j;

for (i = 0; i < N; i++){b[i] = 0.0;for (j = 0; j < N; j++){     //係数行列と厳密解ベクトルを用いて行列-ベクトル積を計算し,

b[i] += A[i + N*j] * x[j]; //結果を右辺ベクトルに代入}

}

}

cg_cpu.c

Page 24: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

CPUプログラム(共役勾配法部分)

2015/10/14GPGPU講習会24

//残差ベクトルの計算 r(0)=b−Ax(0)

computeResidual(r, b, A, x, N);//残差ベクトルの内積を計算rr = innerProduct(r, r, N);

k = 1;while(rr>err_tol*err_tol && k<=max_ite){

if (k == 1){//p(k) = r(k)+c2

(k−1)p(k−1) c2とpが0のためp(k) = r(k)copy(p, r, N);

}else{

c2 = rr / (c1*dot);//p(k) = r(k)+c2

(k−1)p(k−1)

computeVectorAdd(p, c2, r, 1.0, N);}

//(p(k), Ap(k))を計算//行列ベクトル積Apを実行し,結果とpの内積computeMxV(Ax, A, p, N);dot = innerProduct(p, Ax, N);c1 = rr / dot;

//x(k+1) = x(k)+c1(k)p(k)

//r(k+1) = r(k)−c1(k)Ap(k)

computeVectorAdd(x, 1.0,  p, c1, N);computeVectorAdd(r, 1.0, Ax,‐c1, N);

//残差ベクトルの内積を計算rr = innerProduct(r, r, N);

k++;}

/*Compute r(0)=b−Ax(0). Set p(0)=0,c2

(0)=0.For k=1,…, until ||r||/||b|| < , Do

p(k) = r(k)+c2(k−1)p(k−1)

c1(k) = (r(k), r(k))/(p(k), Ap(k))

x(k+1) = x(k)+c1(k)p(k)

r(k+1) = r(k)−c1(k)Ap(k)

c2(k) = (r(k+1), r(k+1))/{c1

(k)(p(k), Ap(k))}EndDo*/ cg_cpu.c

Page 25: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

CPUプログラム(共役勾配法内の関数)

2015/10/14GPGPU講習会25

//残差ベクトルr(0)=b−Ax(0)の計算void computeResidual(double *r, double *b, 

double *A, double *x,int N){

int i,j;double Ax;for (i = 0; i < N; i++){

Ax = 0.0;for (j = 0; j < N; j++){

Ax += A[i + N*j] * x[j];}r[i] = b[i]‐Ax;

}

}

//内積の計算double innerProduct(double *vec1, 

double *vec2, int N){

int i;double dot;

dot=0.0;for (i = 0; i < N; i++){

dot += vec1[i]*vec2[i];}

return dot;

}

cg_cpu.c

Page 26: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

CPUプログラム(共役勾配法内の関数)

2015/10/14GPGPU講習会26

//値のコピー(単純代入)p(k) = r(k)void copy(double *lhs, double *rhs, int N){

int i;for (i = 0; i < N; i++){

lhs[i] = rhs[i];}

}

//ベクトル和y(k) = ax(k) + by(k)の計算void computeVectorAdd(

double *y, const double b, double *x, const double a, 

int N){

int i;for (i = 0; i < N; i++){

y[i] = a*x[i] + b*y[i];}

}

//行列-ベクトル積Axの計算void computeMxV(double *Ax,

double *A, double *x, int N){

int i,j;for (i = 0; i < N; i++){

Ax[i] = 0.0;for (j = 0; j < N; j++){

Ax[i] += A[i + N*j] * x[j];}

}

}

cg_cpu.c

Page 27: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

実行結果(N=210)

2015/10/14GPGPU講習会27

iteration =   1, residual = 2.098826e+003iteration =   2, residual = 4.308518e+002iteration =   3, residual = 1.102497e+002:

iteration =  21, residual = 5.547180e‐009iteration =  22, residual = 1.486358e‐009iteration =  23, residual = 3.982675e‐010x[0] = ‐0.000000x[1] = 1.000000x[2] = 2.000000:

x[1021] = 1021.000000x[1022] = 1022.000000x[1023] = 1023.000000Total amount of Absolute Error = 5.009568e‐010

Page 28: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

収束履歴

2015/10/14GPGPU講習会28

反復回数

残差

Page 29: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLASの紹介

Page 30: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLAS*

2015/10/14GPGPU講習会30

BLASのGPU向け実装 Level 1

ベクトルに対する計算

Level 2 行列-ベクトルの計算

Level 3 行列-行列の計算

BLASはFORTRAN用ライブラリとして開発 C言語から使用する場合には注意が必要

配列の添字は1から

メモリの配置がC言語と異なる

*CUBLASやcublasと書かれる事もあるが,NVIDIAのCUDA Toolkit Documentationの標記に従う

Page 31: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLAS

2015/10/14GPGPU講習会31

関数群はドキュメントを参照

http://docs.nvidia.com/cuda/cublas/

実行する際の並列度の設定は自動

処理内容に対応した関数を呼び出す

cublas<>axpy() <>は用いる型に応じて選択

S 単精度実数

D 倍精度実数

C 単精度複素数型

Z 倍精度複素数型

Page 32: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLAS

2015/10/14GPGPU講習会32

計算内容に対応した関数を呼ぶ事で計算を実行

cublas<>axpy() ベクトル和

cublas<>gemv() 行列‐ベクトル積

cublas<>gemm() 行列‐行列積

コンパイルの際はオプションとして –lcublas を追加

y[] = x[] + y[]

y[] = OP(A[][])x[] + y[]

C[][] = OP(A[][])OP(B[][]) + C[][]

OP(A[][])は行列Aに対する処理(転置など)

Page 33: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

#include<stdio.h>#include<math.h>#include<cublas_v2.h>

#define N 256

int main(){

int i,j;float A[N*N], B[N], C[N];float *d_A, *d_B, *d_C;float alpha, beta;

for(j=0;j<N;j++){for(i=0;i<N;i++){

A[i+N*j] = (float)i/(float)N;}

}

for(i=0;i<N;i++){C[i] = 0.0f;

}for(i=0;i<N;i++){

B[i] = 1.0f;}

cudaMalloc((void**)&d_A, N*N*sizeof(float));

cudaMalloc((void**)&d_B, N*sizeof(float));

cudaMalloc((void**)&d_C, N*sizeof(float));

alpha = 1.0f;beta  = 0.0f;

cuBLASによる行列-ベクトル積

GPGPU講習会33 2015/10/14

cublas_gemv.cu

111

256/2256/2256/2256/1256/1256/1256/0256/0256/0

]2[]1[]0[

ccc

Page 34: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cublasHandle_t handle;cublasCreate(&handle);

cublasSetMatrix(N, N, sizeof(float), A, N, d_A, N);

cublasSetVector(N, sizeof(float), B, 1, d_B, 1);

cublasSetVector(N, sizeof(float), C, 1, d_C, 1);

cublasSgemv(handle, CUBLAS_OP_N, N, N, &alpha,

d_A, N, d_B, 1, &beta, d_C, 1);

cublasGetVector(N, sizeof(float), d_C, 1, C, 1);

for(i=0;i<N;i++){printf("C[%3d] = %f ¥n",j, C[j]);

}

cudaFree(d_A);cudaFree(d_B);cudaFree(d_C);

cublasDestroy(handle);

return 0;}

cuBLASによる行列-ベクトル積

GPGPU講習会34 2015/10/14

cublas_gemv.cu

Page 35: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLASによる行列-ベクトル積

2015/10/14GPGPU講習会35

ヘッダファイルのインクルード #include<cublas_v2.h>

CUBLASのハンドルの作成 cublasHandle_t handle;

cublasCreate(&handle); ハンドル(行列やベクトルの情報を管理)の生成

返値はcublasStatus_t型

GPU上のメモリ確保 cudaMalloc

以前はcublasAlloc()という関数もあったが無くなった

Page 36: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLASによる行列-ベクトル積

2015/10/14GPGPU講習会36

データ転送

cublasSetMatrix(N,N,sizeof(float),A,N,d_A,N);

cublasSetVector(N,sizeof(float),B,1,d_B,1);

cublasSetVector(N,sizeof(float),C,1,d_C,1);

関数内部でcudaMemcpyが呼ばれる それぞれB,d_B, C, d_Cにアクセスする際のストライド

行列(A, d_A)の第1次元の要素数

Page 37: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLASによる行列-ベクトル積

2015/10/14GPGPU講習会37

演算を行う関数の呼び出し

cublasSgemv(handle, CUBLAS_OP_N, N, N, &alpha, d_A, N, d_B, 1, &beta, d_C, 1);

CUBLAS_OP_N 行列Aに対する操作

cublasOperation_t型 CUBLAS_OP_N OP(A)=A 処理しない

CUBLAS_OP_T OP(A)=AT 転置

CUBLAS_OP_C OP(A)=AH 共役転置

C[N] = OP(A[N][N])B[N] + C[N]d_B, d_Cにアクセスする際のストライド

行列d_Aの第1次元の要素数

Page 38: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLASによる行列-ベクトル積

2015/10/14GPGPU講習会38

データの読み戻し

cublasGetVector(N,sizeof(float),d_C,1,C,1);

GPU上のメモリの解放

cudaFree

ハンドルの削除

cublasDestroy(handle);

d_C, Cにアクセス

する際のストライド

Page 39: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLASを使う際の注意点

2015/10/14GPGPU講習会39

行列を表現するときのメモリ配置

A[i][j] 2次元配列でもメモリ上は1次元に配置

i方向が先かj方向が先か

C言語はj方向優先

Fortranはi方向優先

Page 40: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLASを使う際の注意点

2015/10/14GPGPU講習会40

C言語におけるA[i][j]のメモリ上の配置

0/256,0/256,0/256・・・1/256,1/256,1/256・・・2/256,2/256,2/256 ・・・ FortranにおけるA(i,j)のメモリ上の配置

0/256,1/256,2/256・・・0/256,1/256,2/256・・・0/256,1/256,2/256・・・

256/2256/2256/2256/1256/1256/1256/0256/0256/0j

i

Page 41: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLASを使う際の注意点

2015/10/14GPGPU講習会41

C言語におけるA[i][j]のメモリ上の配置

0/256,0/256,0/256・・・1/256,1/256,1/256・・・2/256,2/256,2/256 ・・・ FortranにおけるA(i,j)のメモリ上の配置

0/256,1/256,2/256・・・0/256,1/256,2/256・・・0/256,1/256,2/256・・・

256/2256/2256/2256/1256/1256/1256/0256/0256/0j

i

Page 42: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLASを使う際の注意点

2015/10/14GPGPU講習会42

C言語におけるA[i][j]のメモリ上の配置

0/256,0/256,0/256・・・1/256,1/256,1/256・・・2/256,2/256,2/256 ・・・ FortranにおけるA(i,j)のメモリ上の配置 ←cuBLAS 0/256,1/256,2/256・・・0/256,1/256,2/256・・・0/256,1/256,2/256・・・

256/2256/2256/2256/1256/1256/1256/0256/0256/0j

i

Page 43: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

第1次元の要素数(lda)とは?

2015/10/14GPGPU講習会43

Leading dimension of matrix A 行列Aの一部分だけを取り出せるようにするためのオプション

M行N列の行列としてAを宣言したときのMの値

ldaの指定を間違えると(例えば2を指定すると)

987654321

A M

N

682493571

A

987654321

A

行列サイズに2,2,ldaにM(=3)を指定

行列全体を使って計算するときはldaの値=行数と覚える

Page 44: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

cuBLASによる共役勾配法の実装

Page 45: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

共役勾配法のアルゴリズム(再掲)

2015/10/14GPGPU講習会45

連立一次方程式Ax=bに対する共役勾配法

Compute r(0)=b−Ax(0). Set p(0)=0,c2(0)=0.

For k=1,…, until ||r||/||b|| < , Do

p(k) = r(k)+c2(k−1)p(k−1)

c1(k) = (r(k), r(k))/(p(k), Ap(k))

x(k+1) = x(k)+c1(k)p(k)

r(k+1) = r(k)−c1(k)Ap(k)

c2(k) = (r(k+1), r(k+1))/{c1

(k)(p(k), Ap(k))}

EndDo

Ap 係数行列Aとベクトルpの積

( , ) ベクトル同士の内積

A 係数行列x 解ベクトルb 右辺ベクトルr 残差ベクトルp 補助ベクトル||・|| l2−ノルム

Page 46: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

CPUプログラム(共役勾配法)(再掲)

2015/10/14GPGPU講習会46

//残差ベクトルの計算 r(0)=b−Ax(0)

computeResidual(r, b, A, x, N);//残差ベクトルの内積を計算rr = innerProduct(r, r, N);

k = 1;while(rr>err_tol*err_tol && k<=max_ite){

if (k == 1){//p(k) = r(k)+c2

(k−1)p(k−1) c2とpが0のためp(k) = r(k)copy(p, r, N);

}else{

c2 = rr / (c1*dot);//p(k) = r(k)+c2

(k−1)p(k−1)

computeVectorAdd(p, c2, r, 1.0, N);}

//(p(k), Ap(k))を計算//行列ベクトル積Apを実行し,結果とpの内積computeMxV(Ax, A, p, N);dot = innerProduct(p, Ax, N);c1 = rr / dot;

//x(k+1) = x(k)+c1(k)p(k)

//r(k+1) = r(k)−c1(k)Ap(k)

computeVectorAdd(x, 1.0,  p, c1, N);computeVectorAdd(r, 1.0, Ax,‐c1, N);

//残差ベクトルの内積を計算rr = innerProduct(r, r, N);

k++;}

/*Compute r(0)=b−Ax(0). Set p(0)=0,c2

(0)=0.For k=1,…, until ||r||/||b|| < , Do

p(k) = r(k)+c2(k−1)p(k−1)

c1(k) = (r(k), r(k))/(p(k), Ap(k))

x(k+1) = x(k)+c1(k)p(k)

r(k+1) = r(k)−c1(k)Ap(k)

c2(k) = (r(k+1), r(k+1))/{c1

(k)(p(k), Ap(k))}EndDo*/ cg_cpu.c

Page 47: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

共役勾配法の各処理の置き換え

2015/10/14GPGPU講習会47

共役勾配法に必要な処理とcuBLAS関数の対応

合致する処理が無い場合は処理を分解して対応

処理 cuBLAS関数

ベクトルの代入(y[]=x[]) cublas<>copy

ベクトルのスカラ倍(y[]=a*y[]) cublas<>scal

ベクトル同士の和(y[]=a*x[]+y[]) cublas<>axpy

ベクトルの内積(y=x[]·x[]) cublas<>dot

行列-ベクトル積(y[]=A[][]x[]) cublas<>gemv

Page 48: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

r(0)=b−Ax(0)の置き換え

2015/10/14GPGPU講習会48

いきなり難関

cuBLASはベクトルを2個までしか扱えない

3段階に分けて計算

行列-ベクトル積を計算 r(0)=b−Ax(0)

計算した結果を別の配列(例えばAx)に保持

cublasDgemv

bの値をrに代入 r(0)=r−Ax(0)

bを使う箇所をrに置き換えることができる

cublasDcopy

ベクトル和を計算 r(0)=r−1×Ax(0)

cublasDaxpy

Page 49: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

r(0)=b−Ax(0)の置き換え

2015/10/14GPGPU講習会49

cublasDgemv cublasDgemv(handle, CUBLAS_OP_N, N, N, &one,    

d_A, N, d_x, 1, &zero, d_Ax, 1); Ax[N] = one*A[N][N]x[N] + zero*Ax[N]

cublasDcopy cublasDcopy(handle, N, d_b, 1, d_r, 1); r[N] = b[N]

cublasDaxpy cublasDaxpy(handle, N, &minusOne,d_Ax,1 ,d_r,1); r[N] = r[N] + minusOne*Ax[N]

one =1.0;zero=0.0;

minusOne =‐1.0;

必ず変数のアドレスを指定

Page 50: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

r(0)の内積の計算

2015/10/14GPGPU講習会50

cublasDdot cublasDdot(handle, N, d_r, 1, d_r, 1, &rr); rr = (r[N], r[N])

Page 51: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

p(k) = r(k)+c2(k−1)p(k−1)の置き換え

2015/10/14GPGPU講習会51

k=1 c2=0のため単純な代入 p(k) = r(m)

cublasDcopy

k>1 ベクトル和を計算 p(k) = r(k)+c2

(k−1)p(k−1)

またもや難題

cublasDaxpyでは足されるベクトル(p)への操作はできない

2段階に分けて処理を実行

pの値をc2倍 p(k)=c2×p(k−1)

cublasDscal ベクトル和を計算 p(k) = p(k)+1×r(k)

cublasDaxpy

Page 52: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

p(k) = r(k)+c2(k−1)p(k−1)の置き換え

2015/10/14GPGPU講習会52

cublasDscal cublasDscal(handle, N, &c2, d_p, 1); p[N] = c2*p[N]

cublasDaxpy cublasDaxpy(handle, N, &one,d_r,1 ,d_p,1); p[N] = one*r[N] + p[N]

Page 53: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

係数c1の計算

2015/10/14GPGPU講習会53

r(k)の内積は既に計算済みなので省略

分母(p(k), Ap(k))の計算

2段階に分けて計算

行列-ベクトル積Ap(k)を計算

計算した結果を別の配列(例えばAxを流用)に保持

cublasDgemv

pとAxの内積を計算(p(k), Ap(k)) cublasDdot

c1を計算

Page 54: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

係数c1の計算

2015/10/14GPGPU講習会54

cublasDgemv cublasDgemv(handle, CUBLAS_OP_N, N, N, &one,    

d_A, N, d_p, 1, &zero, d_Ax, 1); Ax[N] = one*OP(A[N][N])p[N] + zero*Ax[N]

cublasDdot cublasDdot(handle, N, d_p, 1, d_Ax, 1, &dot); dot = (p[N], Ax[N])

c1 = rr/dot

Page 55: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

解ベクトルx(k)と残差ベクトルr(k)を更新

2015/10/14GPGPU講習会55

ベクトル和を計算 x(k+1) = x(k)+c1(k)×p(k)

cublasDaxpy(handle, N, &c1,d_p,1 ,d_x,1); x[N] = c1*p[N] + x[N]

ベクトル和を計算 r(k+1) = r(k)−c1(k)×Ap(k)

既に計算した行列-ベクトル積(Ax)を利用

cublasDaxpy(handle, N, &minusC1, d_Ax,1 ,d_r,1); r[N] = minusC1*Ax[N] + r[N]

minusC1 =‐c1;

Page 56: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

係数c2の計算

2015/10/14GPGPU講習会56

分母(p(k), Ap(k))は計算済み

更新されたr(k+1)の内積を計算

cublasDdot(handle, N, d_r, 1, d_r, 1, &rr); rr = (r[N], r[N])

c2 = rr/(c1*dot)

Page 57: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

GPUプログラム(制御部分)

2015/10/14GPGPU講習会57

#include <stdlib.h>#include <stdio.h>#include <cublas_v2.h>int main(void){

int N = 1 << 10;          //未知数の数210const double err_tol = 1e‐9; //許容誤差const int max_ite = 1<<20;//反復回数の上限

double *x; //近似解ベクトルdouble *b; //右辺ベクトルdouble *A; //係数行列double *sol; //厳密解

//GPU用変数double *d_x;double *d_b;double *d_A;double *d_r, rr;double *d_p, *d_Ax;double c1, c2, minusC1, dot;

//cublasで利用する定数const double one = 1.0;const double zero = 0.0;const double minusOne = ‐1.0;int i, k;

A = (double *)malloc(sizeof(double)*N*N);x  = (double *)malloc(sizeof(double)*N);b  = (double *)malloc(sizeof(double)*N);sol= (double *)malloc(sizeof(double)*N);

for (i = 0; i < N; i++){sol[i] = (double)i; //厳密解を設定

x[i] = 0.0;       //近似解を0で初期化}//係数行列Aの生成setTridiagonalMatrix(A, N);//右辺ベクトルbの生成setRightHandSideVector(b, A, sol, N);

cg_cublas.cu

Page 58: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

GPUプログラム(制御部分)

2015/10/14GPGPU講習会58

//cuBLASハンドルの生成cublasHandle_t cublasHandle = 0;cublasStatus_t cublasStatus;cublasStatus=cublasCreate(&cublasHandle);

cudaMalloc((void **)&d_A, N*N*sizeof(double));

cudaMalloc((void **)&d_x, N  *sizeof(double));

cudaMalloc((void **)&d_b, N  *sizeof(double));

cudaMalloc((void **)&d_r, N  *sizeof(double));

cudaMalloc((void **)&d_p, N  *sizeof(double));

cudaMalloc((void **)&d_Ax,N *sizeof(double));

cublasSetMatrix(N, N, sizeof(double), A, N, d_A, N);

cublasSetVector(N, sizeof(double), x, 1, d_x, 1);

cublasSetVector(N, sizeof(double), b, 1, d_b, 1);

//        :// ここで共役勾配法を実行//        :

//ハンドルの破棄cublasDestroy(cublasHandle);

//確保したメモリを解放free(x);free(b);free(A);free(sol);cudaFree(d_x);cudaFree(d_b);cudaFree(d_A);cudaFree(d_r);cudaFree(d_p);cudaFree(d_Ax);

} cg_cublas.cu

Page 59: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

GPUプログラム(共役勾配法部分)

2015/10/14GPGPU講習会59

//残差ベクトルの計算 r(0)=b−Ax(0)

cublasDgemv(cublasHandle, CUBLAS_OP_N, N, N, &one, d_A, N, d_x, 1, &zero, d_Ax, 1);cublasDcopy(cublasHandle, N, d_b, 1, d_r, 1);cublasDaxpy(cublasHandle, N, &minusOne, d_Ax, 1, d_r, 1);//残差ベクトルの内積を計算cublasDdot(cublasHandle, N, d_r, 1, d_r, 1, &rr);

k = 1;while(rr>err_tol*err_tol && k<=max_ite){

if (k == 1){//p(k) = r(k)+c2

(k−1)p(k−1) c2とpが0のためp(k) = r(k)cublasDcopy(cublasHandle, N, d_r, 1, d_p, 1);

}else{

c2 = rr / (c1*dot);//p(k) = r(k)+c2

(k−1)p(k−1)

cublasDscal(cublasHandle, N, &c2, d_p, 1);cublasDaxpy(cublasHandle, N, &one, d_r, 1, d_p, 1);

}cg_cublas.cu

Page 60: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

GPUプログラム(共役勾配法部分)

2015/10/14GPGPU講習会60

//(p(k), Ap(k))を計算//行列ベクトル積Apを実行し,結果とpの内積cublasDgemv(cublasHandle, CUBLAS_OP_N, N, N, &one, d_A, N, d_p, 1, &zero, d_Ax, 1);cublasDdot(cublasHandle, N, d_p, 1, d_Ax, 1, &dot);c1 = rr / dot;

//x(k+1) = x(k)+c1(k)p(k)

//r(k+1) = r(k)−c1(k)Ap(k)

cublasDaxpy(cublasHandle, N, &c1, d_p, 1, d_x, 1);cublasDaxpy(cublasHandle, N, &minusC1, d_Ax, 1, d_r, 1);

//残差ベクトルの内積を計算cublasDdot(cublasHandle, N, d_r, 1, d_r, 1, &rr);

cudaDeviceSynchronize();k++;

}

//計算結果をGPUからCPUへコピーcublasGetVector(N, sizeof(double), d_x, 1, x, 1);

cg_cublas.cu

Page 61: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

実行時間の比較

2015/10/14GPGPU講習会61

ベクトルの次元 CPU [sec/iteration]

cuBLAS[sec/iteration]

210 8.26×10‐3 0.553×10‐3

211 39.6×10‐3 0.865×10‐3

212 231×10‐3 1.84×10‐3

213 1.20 5.78×10‐3

214 6.06 23.0×10‐3

Page 62: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

実行時間の比較

2015/10/14GPGPU講習会62

ベクトルの次元

1反復あたりの実行時間[sec]

Page 63: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

改善点

2015/10/14GPGPU講習会63

ベクトルの次元214は多いか? 少なすぎて話にならない

現在のシミュレーションでは220~230(数千万から数億)

行列の格納形式

無駄が多い

配列要素数に対する非ゼロ要素の割合

(2+(N‐2)*3+2) / N2

N=214のとき非ゼロ要素の割合は0.02%

改善点

行列の非ゼロ要素のみを格納してメモリ利用効率を上げる* cuSPARSEを利用

41141

14114

0

0

*cuBLASにも帯行列‐ベクトル積を計算する関数があるので,それを使えば0要素を保持しなくてもよくなる.調査してみよう.

Page 64: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

補足

Page 65: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

A. cuBLAS関数のリファレンス

2015/10/14GPGPU講習会65

cublasCreate cublasStatus_tcublasCreate(cublasHandle_t *handle)

cublasDestroy cublasStatus_tcublasDestroy(cublasHandle_t handle)

cuBLASのハンドルのアドレス

cuBLASのハンドル

Page 66: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

A. cuBLAS関数のリファレンス

2015/10/14GPGPU講習会66

cublasSetVector y[n]<‐x[n] cublasStatus_tcublasSetVector(int n,

int elemSize,const void *x,int incx,void *y,int incy)

ベクトルの要素数

1要素のバイト数

コピー元ベクトルのアドレス

コピー元ベクトルのストライド

コピー先ベクトルのアドレス

コピー先ベクトルのストライド

Page 67: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

A. cuBLAS関数のリファレンス

2015/10/14GPGPU講習会67

cublasGetVector y[n]<‐x[n] cublasStatus_tcublasGetVector(int n,

int elemSize,const void *x,int incx,void *y,int incy)

ベクトルの要素数

1要素のバイト数

コピー元ベクトルのアドレス

コピー元ベクトルのストライド

コピー先ベクトルのアドレス

コピー先ベクトルのストライド

Page 68: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

A. cuBLAS関数のリファレンス

2015/10/14GPGPU講習会68

cublasSetMatrix B[rows][cols]<‐A[rows][cols] cublasStatus_tcublasSetMatrix(int rows,

int cols,int elemSize,const void *A,int lda,void *B,int ldb)

行の要素数

列の要素数

1要素のバイト数

コピー元行列のアドレス

コピー元行列の1次元の要素数

コピー先行列のアドレス

コピー先行列の1次元の要素数

Page 69: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

A. cuBLAS関数のリファレンス

2015/10/14GPGPU講習会69

cublasGetMatrix B[rows][cols]<‐A[rows][cols] cublasStatus_tcublasGetMatrix(int rows,

int cols,int elemSize,const void *A,int lda,void *B,int ldb)

行の要素数

列の要素数

1要素のバイト数

コピー元行列のアドレス

コピー元行列の1次元の要素数

コピー先行列のアドレス

コピー先行列の1次元の要素数

Page 70: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

A. cuBLAS関数のリファレンス

2015/10/14GPGPU講習会70

cublasDcopy y[n]<‐x[n] cublasStatus_tcublasDcopy(cublasHandle_t handle,

int n,const double *x,int incx,double *y,int incy)

ハンドル

ベクトルの要素数

コピー元ベクトルのアドレス

コピー元ベクトルのストライド

コピー先ベクトルのアドレス

コピー先ベクトルのストライド

Page 71: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

A. cuBLAS関数のリファレンス

2015/10/14GPGPU講習会71

cublasDdot result <‐ (x[n]·y[n]) cublasStatus_tcublasDdot (cublasHandle_t handle,

int n,const double *x,int incx,const double *y,int incy,double *result)

ハンドル

ベクトルの要素数

一つ目のベクトルのアドレス

一つ目のベクトルのストライド

二つ目のベクトルのアドレス

二つ目のベクトルのストライド

内積の結果を格納する変数のアドレス

Page 72: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

A. cuBLAS関数のリファレンス

2015/10/14GPGPU講習会72

cublasDscal x[n]<‐alpha*x[n] cublasStatus_tcublasDscal(cublasHandle_t handle,

int n,const double *alpha,double *x,int incx)

ハンドル

ベクトルの要素数

かける数を代入した変数のアドレス

入出力ベクトルのアドレス

入出力ベクトルのストライド

Page 73: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

A. cuBLAS関数のリファレンス

2015/10/14GPGPU講習会73

cublasDaxpy y[n]<‐alpha*x[n] + y[n] cublasStatus_tcublasDaxpy(cublasHandle_t handle,

int n,const double *alpha,const double *x,int incx,double *y,int incy)

ハンドル

ベクトルの要素数

かける数を代入した変数のアドレス

加算するベクトルのアドレス

加算するベクトルのストライド

加算されるベクトルのアドレス

加算されるベクトルのストライド

Page 74: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

A. cuBLAS関数のリファレンス

2015/10/14GPGPU講習会74

cublasDgemv y[m] = alpha*OP(A[m][n])x[n] + beta*y[m] cublasStatus_tcublasDgemv(cublasHandle_t handle,

cublasOperation_t trans,

int m, int n,

const double *alpha,

const double *A, int lda,

const double *x, int incx,

const double *beta,

double *y, int incy)

ハンドル

行列に対する操作

行列の行と列の要素数

かける数を代入した変数のアドレス

行列と1次元の要素数

行列にかけるベクトルのアドレスとストライド

計算結果のベクトルにかける数を代入した変数のアドレス

計算結果のベクトルのアドレスとストライド

Page 75: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

B. 実行時間の測定

GPGPU講習会75

#include<time.h> // clock_t型や関数clock()を利用

int main(void){clock_t start_c, stop_c;float   time_s;

start_c = clock(); //プログラム実行時からの経過時間を取得: //: //ここに処理を記述: //

stop_c = clock(); //プログラム実行時からの経過時間を取得

//処理に要した時間を秒に変換time_s = (stop_c‐start_c)/(float)CLOCKS_PER_SEC;printf(...); //画面表示

return 0;}

2015/10/14

Page 76: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

B. 実行時間の測定

CPUで時間計測はできない

clock関数を使うと実行時間を正しく測定できない

CUDAで用意されている関数を使って時間を計測

2015/10/14GPGPU講習会76

初期化の指示初期化

カーネルの実行指示カーネルを実行

結果の取得実行結果をコピー

time

CPUとGPUは非同期CPUは別の処理を実行可能

必要なデータのコピーメモリに書込

Page 77: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

C. CPUコードの実行時間の測定

2015/10/14GPGPU講習会77

#include<time.h> // clock_t型や関数clock()を利用

int main(void){clock_t start_c, stop_c;float   time_s;

start_c = clock(); //プログラム実行時からの経過時間を取得: //: //ここに処理を記述: //

stop_c = clock(); //プログラム実行時からの経過時間を取得

//処理に要した時間を秒に変換time_s = (stop_c‐start_c)/(float)CLOCKS_PER_SEC;printf(...); //画面表示

return 0;}

Page 78: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

D. CUDA Eventで時間測定*

GPUへの指示をEventと呼び,そのEventが発生した時間の差から時間を測定

準備

どのEventを取り扱うかを宣言

kernelの呼び出し(startイベント)と実行終了(stopイベント)

イベントを取り扱う変数の宣言と利用準備

*http://gpu.fixstars.com/index.php/CUDA_Eventで時間計測

2015/10/14GPGPU講習会78

cudaEvent_t start,stop;       ・・・イベントを取り扱う変数float elapsed_time_ms = 0.0f; ・・・経過時間保存用

cudaEventCreate(&start);      ・・・イベントのクリエイトcudaEventCreate(&stop);

Page 79: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

D. CUDA Eventで時間測定

Event発生時間を記録

Eventの同期

startとstopの時間を正しく記録し終わっていることを保証

2015/10/14GPGPU講習会79

cudaEventRecord(start, 0);//ここでkernelを実行cudaEventRecord(stop, 0);

cudaEventSynchronize(stop);

Page 80: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

D. CUDA Eventで時間測定

Eventが発生した時間差を計算(ミリ秒単位)

Eventの時間を記録した変数を破棄

2015/10/14GPGPU講習会80

cudaEventElapsedTime(&elapsed_time_ms, start,stop);

cudaEventDestroy(start);cudaEventDestroy(stop);

Page 81: GPGPU Seminar (GPU Accelerated Libraries, 1 of 3, cuBLAS)

D. CUDA Eventで時間測定

int main(void){float *a,*b,*c;//イベント記録の準備

cudaMalloc((void **)&a, Nbytes);cudaMalloc((void **)&b, Nbytes);cudaMalloc((void **)&c, Nbytes);

init<<<   ,   >>>(a,b,c);

//イベント発生時間の記録add<<<   ,   >>>(a,b,c);//イベント発生時間の記録//イベントの同期//イベント間の時間差を計算printf("%f¥n", elapsed_time_ms);//イベントの破棄return 0;

}

2015/10/14GPGPU講習会81