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

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

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

NUMAの構成

Slide 1

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

概要 OpenACC とは OpenACC について OpenMP, CUDA との違い OpenACC の指示文 並列化領域指定指示文 (kernels/parallel) データ移動指示文 ループ指示文 OpenACC の実用例 実習 コンパイラメッセージの見方 OpenACC プログラムの実装

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

( CUDA CUDA CUDA CUDA ( NVIDIA CUDA I

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

2 09:00-09:30 受付 09:30-12:00 GPU 入門,CUDA 入門 13:00-14:30 OpenACC 入門 + HA-PACS ログイン 14:45-16:15 OpenACC 最適化入門と演習 16:30-18:00 CUDA 最適化入門と演習

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

Slide 1

スライド 1

GPU.....

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

インテル(R) Visual Fortran Composer XE 2013 Windows版 入門ガイド

OpenACC

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

memo

演習1: 演習準備

PowerPoint プレゼンテーション

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

OpenACCによる並列化

Fortran 勉強会 第 5 回 辻野智紀

XACCの概要

untitled

XMPによる並列化実装2

Microsoft PowerPoint - 03_What is OpenMP 4.0 other_Jan18

Microsoft PowerPoint - 講義:コミュニケータ.pptx

01_OpenMP_osx.indd

11042 計算機言語7回目 サポートページ:

HPC143

memo

memo

Microsoft PowerPoint - KHPCSS pptx

DO 時間積分 START 反変速度の計算 contravariant_velocity 移流項の計算 advection_adams_bashforth_2nd DO implicit loop( 陰解法 ) 速度勾配, 温度勾配の計算 gradient_cell_center_surface 速

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

プログラミング実習I

GPU CUDA CUDA 2010/06/28 1

untitled

Microsoft PowerPoint - 09.pptx

並列・高速化を実現するための 高速化サービスの概要と事例紹介

ex01.dvi

02: 変数と標準入出力

<4D F736F F F696E74202D D F95C097F D834F E F93FC96E5284D F96E291E85F8DE391E52E >

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

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

数はファイル内のどの関数からでも参照できるので便利ではありますが 変数の衝突が起こったり ファイル内のどこで値が書き換えられたかわかりづらくなったりなどの欠点があります 複数の関数で変数を共有する時は出来るだけ引数を使うようにし グローバル変数は プログラムの全体の状態を表すものなど最低限のものに留

GPGPUイントロダクション

演習2

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

1F90/kouhou_hf90.dvi

XACC講習会

コンピュータ工学講義プリント (7 月 17 日 ) 今回の講義では フローチャートについて学ぶ フローチャートとはフローチャートは コンピュータプログラムの処理の流れを視覚的に表し 処理の全体像を把握しやすくするために書く図である 日本語では流れ図という 図 1 は ユーザーに 0 以上の整数 n

第9回 配列(array)型の変数

PowerPoint Presentation

untitled

コマンドラインから受け取った文字列の大文字と小文字を変換するプログラムを作成せよ 入力は 1 バイトの表示文字とし アルファベット文字以外は変換しない 1. #include <stdio.h> 2. #include <ctype.h> /*troupper,islower,isupper,tol

Microsoft PowerPoint - 演習2:MPI初歩.pptx

Microsoft PowerPoint - 先端GPGPUシミュレーション工学特論(web).pptx

演習1

フローチャートの書き方

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

Microsoft Word - no11.docx

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

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

PowerPoint プレゼンテーション

Microsoft Word - VBA基礎(6).docx

NUMAの構成

Microsoft PowerPoint - OpenMP入門.pptx

7 ポインタ (P.61) ポインタを使うと, メモリ上のデータを直接操作することができる. 例えばデータの変更 やコピーなどが簡単にできる. また処理が高速になる. 7.1 ポインタの概念 変数を次のように宣言すると, int num; メモリにその領域が確保される. 仮にその開始のアドレスを 1

演習課題No12

ex01.dvi

HPC146

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

cp-7. 配列

分割コンパイル (2018 年度 ) 担当 : 笹倉 佐藤 分割コンパイルとは 一つのプログラムのソースを複数のソースファイルに分けてコンパイルすること ある程度大きなプログラムの場合ソースファイルをいくつかに分割して開発するのが普通 1

Microsoft PowerPoint ppt

Microsoft PowerPoint - C言語の復習(配布用).ppt [互換モード]

slide5.pptx

02: 変数と標準入出力

XcalableMP入門

program7app.ppt

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

コードのチューニング

1.overview

情報処理概論(第二日目)

(1) プログラムの開始場所はいつでも main( ) メソッドから始まる 順番に実行され add( a,b) が実行される これは メソッドを呼び出す ともいう (2)add( ) メソッドに実行が移る この際 add( ) メソッド呼び出し時の a と b の値がそれぞれ add( ) メソッド

Microsoft PowerPoint - lec10.ppt

Microsoft Word - openmp-txt.doc

Slide 1

02_C-C++_osx.indd

PowerPoint プレゼンテーション

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

nakao

Microsoft PowerPoint - 講義:片方向通信.pptx

about MPI

Prog1_6th

Vol.214-HPC-145 No /7/3 C #pragma acc directive-name [clause [[,] clause] ] new-line structured block Fortran!$acc directive-name [clause [[,] c

Transcription:

1 09:30-10:00 受付 10:00-12:00 Reedbush-H ログイン GPU 入門 13:30-15:00 OpenACC 入門 15:15-16:45 OpenACC 最適化入門と演習 17:00-18:00 OpenACC の活用 (CUDA 連携とライブラリの活用 )

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

3 OpenACC 簡単にGPUプログラムが作成できる それなりの性能が得られる 様々な環境で利用できる CUDA OpenACCと比べると使用が大変だが より高い性能が期待できる ( 基本的に )NVIDIA GPU 専用 OpenACC プログラムの一部を CUDA 化することで簡単さと高性能を両立できるのでは? 誰かが書いた ( 公開している )CUDAプログラム( 関数 ライブラリ ) を自分のOpenACCプログラムから使わせてもらう 自分が作成したOpenACCプログラムの一部をCUDAで高速化する

4 NVIDIA GPU のハードウェアアーキテクチャに対応した言語 適切な記述をすることでNVIDIA GPUの性能を引き出せる可能性がある C 言語版はCUDA CとしてNVIDIAが提供 開発環境は無償 Fortran 版はCUDA FortranとしてPGIが提供 PGIコンパイラが必要 無料プランも有 言語拡張仕様 コンパイラ ライブラリを提供 言語拡張 :GPUカーネルや使用するメモリの種類を明示する記述 コンパイラ :nvcc ライブラリ : 数値計算ライブラリや機械学習ライブラリなど GPU カーネルを動かす単位は関数 関数単位で並列度を指定してGPUカーネルを起動 グローバルメモリに置かれたデータのみが関数間で引き継がれる

int main(int argc, char **argv) { int i, N; float *A, *B, *C; float *da, *db, *dc; 5 cuda_c.cu global void gpukernel (int N, float *C, float *A, float *B) { int id = blockidx.x*blockdim.x + threadidx.x; if(id<n)c[id] += A[id] * B[id]; GPU 上の各計算コアが行う処理を global void 関数として記述 ( 右上へ続く ) N = 128; A = (float*)malloc(sizeof(float)*n); B = (float*)malloc(sizeof(float)*n); C = (float*)malloc(sizeof(float)*n); for(i=0;i<n;i++){ C[i] = 0.0f; B[i] = 2.0f; A[i] = (float)(i+1)/(float)(n); cudamalloc((void**)&da, sizeof(float)*n); cudamalloc((void**)&db, sizeof(float)*n); cudamalloc((void**)&dc, sizeof(float)*n); cudamemcpy(da, A, sizeof(float)*n, cudamemcpyhosttodevice); cudamemcpy(db, B, sizeof(float)*n, cudamemcpyhosttodevice); cudamemcpy(dc, C, sizeof(float)*n, cudamemcpyhosttodevice); 典型的 CUDA Cプログラムの処理の流れ 1. GPU 上のメモリを確保 2. CPUからGPUへのデータ転送 3. 特殊な記法でGPUカーネルを起動 4. GPUからCPUへのデータ転送 5. GPU 上のメモリを破棄 (1,2,4,5は用意されている専用の関数によって行う ) dim3 grids; dim3 blocks; grids = dim3(4, 1, 1); blocks = dim3(64, 1,1); gpukernel<<<grids,blocks>>>(n, dc, da, db); cudamemcpy(c, dc, sizeof(float)*n, cudamemcpydevicetohost); cudafree(da); cudafree(db); cudafree(dc); free(a); free(b); free(c); return 0; nvcc でコンパイルして実行する $ nvcc cuda_c.cu;./a.out 並列度は GPU カーネル呼び出し時に個別に指定

6 cuda_f.cuf module gpukernel contains attributes(global) subroutine gpukernel(n, C, A, B) integer,value :: ID, N real(kind=4), device, dimension(n), intent(in) :: A, B real(kind=4), device, dimension(n), intent(inout) :: C ID = (blockidx%x 1)*blockDim%x + threadidx%x if(id.le.n)then C(ID) = C(ID) + A(ID) * B(ID) endif end subroutine gpukernel end module gpukernel GPU 上の各計算コアが行う処理を attribute(global) サブルーチン関数として記述 ( 右上へ続く ) CUDA Fortranプログラムの方が少し簡単 CPU 上の配列とGPU 上の配列を明示的に宣言できるため データのコピーが自動的に行われる program main use cudafor use gpukernel implicit none real(4), allocatable, dimension(:) :: A, B, C real(4), allocatable, dimension(:),device :: da, db, dc integer :: I, N type(dim3) :: dimgrid, dimblock N = 128 allocate(a(n), B(N), C(N)) allocate(da(n), db(n), dc(n)) C = 0.0; B = 2.0 do I=1, N A(I) = real(i)/real(n) enddo da = A; db = B; dc = C dimgrid = dim3(2,1,1) dimblock = dim3(64,1,1) call gpukernel<<<dimgrid, dimblock>>>(n, dc, da, db) C = dc cudafor モジュールを使う CPU から GPU へのデータ転送 GPU から CPU へのデータ転送 deallocate(da, db, dc); deallocate(a, B, C) end program main -Mcuda を指定してコンパイルして実行する $ pgf90 -Mcuda cuda_f.cuf;./a.out

7 そもそも OpenACC 指示文を含むソースコードとCUDA 記法を含むソースコードを分けておいて個別にコンパイルし 1 つのプログラムにまとめて使うこと自体は可能 単純にOpenACCとCUDAのソース ( 関数 ) を組み合わせて利用した場合 OpenACCとCUDAを行き来する度にデータのコピーが必要になってしまい性能低下要因となる OpenACCによるデータ送受信 (data 指示文による処理 ) と CUDAにおけるデータの扱い ( 接頭辞やAPIによる指定と処理 ) の橋渡し役が必要

8 C 言語ベースの場合 Fortran ベースの場合 #pragma acc enter data copyin( ) #pragma acc kernels OpenACCによる計算 #pragma acc end kernels!$acc enter data copyin( )!$acc kernels!$acc end kernels CUDA による計算 #pragma acc exit data copyout( )!$acc exit data copyout( ) 一つの data 指示文の中では OpenACC カーネルと CUDA カーネルでデータを共有させたい

9 GPU 上に存在するデータ ( 配列 ) の存在を伝えるための指示文を用いる 使い方 acc host_data use_device( 対象とする配列名 )

10 cudakernel.cu global void gpukernel(int N, float *C, float *A, float *B) { int id = blockidx.x*blockdim.x + threadidx.x; C[id] += A[id] * B[id]; GPU カーネルは CUDA C のみの場合と同様 extern "C" void gpukernel_wrapper(int N, float *C, float *A, float *B) { dim3 grids; dim3 blocks; grids = dim3(2, 1, 1); blocks = dim3(64, 1,1); gpukernel<<<grids,blocks>>>(n, C, A, B); GPU カーネルを起動する関数 C++ ではなく C から使う場合は extern C が必要 CPU-GPU 間のデータ転送については何も記述しなくて良い

11 acc_main.c OpenACC CUDA #include <stdio.h> extern void gpukernel_wrapper(int N, float *C, float *A, float *B); int main(int argc, char **argv){ int i, N; float *A, *B, *C; N = 128; A = (float*)malloc(sizeof(float)*n); B = (float*)malloc(sizeof(float)*n); C = (float*)malloc(sizeof(float)*n); for(i=0;i<n;i++){ C[i] = 0.0f; B[i] = 2.0f; A[i] = (float)(i+1)/(float)(n); #pragma acc enter data copyin(a[0:n],b[0:n],c[0:n]) #pragma acc kernels present(a,b,c) #pragma acc loop independent for(i=0; i<n; i++){ C[i] += A[i] * B[i]; #pragma acc host_data use_device(a,b,c) { gpukernel_wrapper(n, C, A, B); #pragma acc exit data copyout(c[0:n]) free(a); free(b); free(c); return 0; GPU カーネルを起動する関数 を実行することで GPU を動かしている

12 CUDA C 部分はnvccでコンパイルする必要がある点に注意 最低限必要な引数指定などの例 nvcc c cudakernel.cu pgcc acc c acc_main.c pgcc Mcuda acc cudakernel.o acc_main.o 最適化オプションなどを加えた例 -Mcuda と -acc 両方の指定が必要なところに注意する nvcc O2 gencode arch=compute_60,code= "sm_60,compute_60 c cudakernel.cu pgcc acc O2 ta=tesla,cc60 Minfo c acc_main.c pgcc Mcuda acc cudakernel.o acc_main.o 実行./a.out

13 cudakernel.cuf module gpukernel contains attributes(global) subroutine gpukernel(n, C, A, B) integer,value :: ID, N real(kind=4), device, dimension(n), intent(in) :: A, B real(kind=4), device, dimension(n), intent(inout) :: C ID = (blockidx%x 1)*blockDim%x + threadidx%x if(id.le.n)then C(ID) = C(ID) + A(ID) * B(ID) endif end subroutine gpukernel GPU カーネルは CUDA Fortran と同様 subroutine gpukernel_wrapper(n, C, A, B) use cudafor integer, intent(in) :: N real(kind=4), device, dimension(n), intent(in) :: A, B real(kind=4), device, dimension(n), intent(inout) :: C type(dim3) :: dimgrid, dimblock dimgrid = dim3(2,1,1) dimblock = dim3(64,1,1) call gpukernel<<<dimgrid, dimblock>>>(n, C, A, B) end subroutine gpukernel_wrapper end module どちらも device による指定は必要 GPUカーネルを起動する関数 CPU-GPU 間のデータ転送については何も記述していない

14 acc_main.f90 OpenACC CUDA program main use gpukernel implicit none real(4), allocatable, dimension(:) :: A, B, C integer :: I, N N = 128 allocate(a(n), B(N), C(N)) C = 0.0; B = 2.0 do I=1, N A(I) = real(i)/real(n) enddo!$acc enter data copyin(a(1:n), B(1:N), C(1:N))!$acc kernels!$acc loop do I=1, N C(I) = C(I) + A(I) * B(I) enddo!$acc end kernels!$acc host_data use_device(a, B, C) call gpukernel_wrapper(n, C, A, B)!$acc end host_data!$acc exit data copyout(c(1:n)) deallocate(a, B, C) end program main GPU カーネルを起動する関数 を実行することで GPU を動かしている

15 nvccは使わない 最低限必要な引数指定などの例 pgf90 Mcuda c cudakernel.cuf pgf90 acc c acc_main.f90 pgf90 Mcuda acc cudakernel.o acc_main.o 最適化オプションなどを加えた例 pgf90 Mcuda=cc20 O2 Minfo c cudakernel.cuf pgf90 acc O2 ta=tesla,cc60 Minfo c acc_main.f90 pgf90 Mcuda acc cudakernel.o acc_main.o 実行./a.out

16 CUDA C/Fortranで書かれたプログラムに対してOpenACC コードを追加したいこともあるかもしれない CUDA C/Fortranプログラムによって用意された配列を OpenACCカーネルから利用する必要がある deviceptr 節を使用する OpenACC 側では配列の確保や転送を書く必要がない

17 cuda_main.cu extern "C" void acckernel(int N, float *A, float *B, float *C); global void gpukernel(int N, float *C, float *A, float *B) { 通常の CUDA カーネル記述 ( 省略 ) main 関数内 ( 通常の CUDA C 記述 メモリ解放は省略 ) A = (float*)malloc(sizeof(float)*n); B = (float*)malloc(sizeof(float)*n); C = (float*)malloc(sizeof(float)*n); cudamalloc((void**)&da, sizeof(float)*n); cudamalloc((void**)&db, sizeof(float)*n); cudamalloc((void**)&dc, sizeof(float)*n); cudamemcpy(da, A, sizeof(float)*n, cudamemcpyhosttodevice); cudamemcpy(db, B, sizeof(float)*n, cudamemcpyhosttodevice); cudamemcpy(dc, C, sizeof(float)*n, cudamemcpyhosttodevice); gpukernel<<<grids,blocks>>>(n, dc, da, db); acckernel(n, dc, da, db); cudamemcpy(c, dc, sizeof(float)*n, cudamemcpydevicetohost); acckernel.c void acckernel (int N, float *C, float *A, float *B) { #pragma acc kernels deviceptr(a,b,c) #pragma acc loop independent for(int i=0; i<n; i++){ C[i] += A[i] * B[i]; cudamalloc で確保した配列を渡し deviceptr で受ける pgcc acc O2 Minfo ta=tesla,cc60 c acckernel.c nvcc O2 gencode arch=compute_60,code= "sm_60,compute_60 " c cuda_main.cu pgcc Mcuda=cc20 acc o hybrid2 acckernel.o cuda_main.o

18 cuda_main.cuf module cudakernel contains attributes(global) subroutine cudakernel(n, C, A, B) integer,value :: ID, N real(4), device :: A(:), B(:), C(:) ID = (blockidx%x 1)*blockDim%x + threadidx%x GPU カーネルの記述は省略 end subroutine cudakernel end module cudakernel program main use cudafor use cudakernel use acckernel implicit none real(4), allocatable, dimension(:) :: A, B, C real(4), allocatable,device :: da(:), db(:), dc(:) allocate と初期化は省略 解放も省略 da = A; db = B; dc = C dimgrid = dim3(2,1,1) dimblock = dim3(64,1,1) call cudakernel<<<dimgrid, dimblock>>>(n, dc, da, db) call acckernel(n, dc, da, db) C = dc acckernel.f90 module acckernel contains subroutine acckernel(n, C, A, B) integer :: I, N real(4), device :: A(:), B(:), C(:)!$acc kernels deviceptr(a,b,c)!$acc loop do I=1, N C(I) = C(I) + A(I) * B(I) enddo!$acc end kernels end subroutine acckernel end module acckernel デバイス用に確保した配列を渡し deviceptr で受ける,device の為に acckernel.f90 にも -Mcuda オプションが必要 pgf90 Mcuda acc ta=tesla,cc60 O2 Minfo c acckernel.f90 pgf90 Mcuda=cc60 O2 Minfo c cuda_main.cuf pgf90 Mcuda=cc60 acc o hybrid2 cuda_main.o acckernel.o

19 CUDA 用に用意されているライブラリをOpenACCから利用したい グローバルメモリにデータを配置した状態から関数を呼び出すだけのものであればhost_data / use_deviceを利用することで実現が可能 ライブラリの提供する専用関数で値を設定するようなものは困難

20 メモリ解放などの処理は省略 cudamalloc((void**)&da, sizeof(float)*n*n); cudamalloc((void**)&db, sizeof(float)*n*n); cudamalloc((void**)&dc, sizeof(float)*n*n); cudamemcpy(da, A, sizeof(float)*n*n, cudamemcpyhosttodevice); cudamemcpy(db, B, sizeof(float)*n*n, cudamemcpyhosttodevice); cudamemcpy(dc, C, sizeof(float)*n*n, cudamemcpyhosttodevice); cublascreate(&handle); cublassgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, N, N, N, &alpha, da, N, db, N, &beta, dc, N); cudamemcpy(c, dc, sizeof(float)*n*n, cudamemcpydevicetohost); 上 :CUDA C + CUBLAS cudamallocとcudamemcpyでデータを準備し GPU 側の配列を引数に与えてcublas 関数を実行コンパイル例 :nvcc -O3 -lcublas cublas.c 下 :OpenACC + CUBLAS data 指示文でデータ転送 host_data/use_deviceで指示をしてからcublas 関数を実行コンパイル例 :pgcc -Mcuda -acc -O3 -ta=tesla,cc60 -lcublas hybrid.c cublascreate(&handle); #pragma acc enter data copyin(a[0:n*n], B[0:N*N], C[0:N*N]) #pragma acc host_data use_device(a, B, C) { cublassgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, N, N, N, &alpha, A, N, B, N, &beta, C, N); #pragma acc exit data copyout(c[0:n*n])

21 メモリ解放などの処理は省略 use cublas real(4), allocatable, dimension(:,:) :: A, B, C real(4), allocatable, dimension(:,:),device :: da, db, dc allocate(a(n,n), B(N,N), C(N,N)) allocate(da(n,n), db(n,n), dc(n,n)) da = A; db = B; dc = C call cublassgemm('n','n',n,n,n,alpha,da,n,db,n,beta,dc,n) C = dc 上 :CUDA Fortran + CUBLAS CUDA Fortran の書き方で GPU 上のメモリを準備し GPU 側の配列を引数に与えて cublas 関数 を実行コンパイル例 :pgf90 -O3 cublas.cuf 下 :OpenACC + CUBLAS data 指示文でデータ転送 host_data/use_device で指示をしてから cublas 関数を実行コンパイル例 :pgf90 -Mcuda -acc -O3 -ta=tesla,cc60 hybrid.f90 use cublas real(4), allocatable, dimension(:,:) :: A, B, C allocate(a(n,n), B(N,N), C(N,N))!$acc enter data copyin(a(1:n,1:n), B(1:N,1:N), C(1:N,1:N))!$acc host_data use_device(a, B, C) call cublassgemm('n','n',n,n,n,alpha,a,n,b,n,beta,c,n)!$acc end host_data!$acc exit data copyout(c(1:n,1:n)) どちらの実装も C 版と異なり -lcublas 指定がないが use cublas が入っているためライブラリがリンクされる

22 OpenACC による単純な行列積実装と CUBLAS による高速な行列積実装の性能を比較した 正方行列同士の単純な行列積計算 ACC:OpenACCによる単純な実装 ( 外部 2 重ループの並列化 ) CUBLAS:cublassgemmを利用 hybrid:openaccからcublassgemmを呼び出し CPU : MKL sgemm CPU : Xeon E5-2680 v2 icc 16.0.3, mkl=parallel GPU : Tesla K40c pgcc 16.9, -O3 -ta=tesla,cc35 実行時間 ( ミリ秒 ) 1000 100 10 1 CUBLAS の直接利用と OpenACC からの利用に有意な性能差は無し C でも Fortran でも有意な性能差は無し 1000 2000 一辺のサイズ ACC CUBLAS hybrid CPU

23 OpenACCとCUDAの連携 OpenACCと (CUDA 向け ) ライブラリの連携について紹介した 連携させる方法自体はあまり難しくはないため 使い勝手と性能を考えて適切な実装方法を選ぶのが良い 対象とする問題にあった高性能な実装やライブラリが存在する場合には積極的に活用するべき