CUDAやOpenACCによる GPUコンピューティング · CUDA やOpenACCによる ......
Transcript of CUDAやOpenACCによる GPUコンピューティング · CUDA やOpenACCによる ......
Akira Naruse, 8 May 2019
CUDAやOpenACCによるGPUコンピューティング
2
AGENDA
▪ GPU Computing
▪ Pascal GPUs (Tesla P100)
▪ OpenACC
▪ CUDA
3
GPU Computing
4
GPUコンピューティングLow latency + High throughput
CPU GPU
5
アプリケーション実行
アプリケーション・コード
GPU
CPU
並列部分はGPUで実行
計算の重い部分
逐次部分はCPU上で実行
Do i=1,N
End do
6
GPUの構造 (TESLA P100)
64 CUDA core/SM
大量のCUDAコア並列性の抽出が鍵
56 SM/chip
3584 CUDA core/chip
7
GPU APPLICATIONS
数百のアプリケーションがGPUに対応www.nvidia.com/object/gpu-applications.html
8
LEADING APPLICATIONS
9
アプリをGPU対応する方法
Application
CUDAOpenACCLibrary
GPU対応ライブラリにチェンジ
簡単に開始
主要処理をCUDAで記述
高い自由度既存コードにディレクティブを挿
入
簡単に加速
10
NVIDIA LIBRARIES
cuRAND Thrust
cuDNN
AmgXcuBLAS
cuFFT
cuSPARSE cuSOLVER
Performance Primitives NCCL
nvGRAPH
TensorRT
11
PARTNER LIBRARIES
Computer Vision
Sparse direct solvers
Sparse Iterative MethodsLinear Algebra
Linear Algebra
Graph
Audio and Video Matrix, Signal and Image
Math, Signal and Image Linear Algebra
Computational Geometry
Real-time visual simulation
12
アプリをGPU対応する方法
Application
Library
GPU対応ライブラリにチェンジ
簡単に開始
CUDAOpenACC
主要処理をCUDAで記述
高い自由度既存コードにディレクティブを挿
入
簡単に加速
13
void saxpy(int n,
float a,
float *x,
float *restrict y)
{
#pragma acc parallel copy(y[:n]) copyin(x[:n])
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
SAXPY (Y=A*X+Y)
OpenMP OpenACC
void saxpy(int n,
float a,
float *x,
float *restrict y)
{
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
void saxpy(int n,
float a,
float *x,
float *restrict y)
{
#pragma omp parallel for
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
14
アプリをGPU対応する方法
Application
Library OpenACC CUDA
GPU対応ライブラリにチェンジ
簡単に開始
主要処理をCUDAで記述
高い自由度既存コードにディレクティブを挿
入
簡単に加速
15
__global__ void saxpy(int n, float a,
float *x, float *y)
{
int i = threadIdx.x + blodkDim.x * blockIdx;
if (i < n)
y[i] += a*x[i];
}
...
size_t size = sizeof(float) * N;
cudaMemcpy(d_x, x, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_y, y, size, cudaMemcpyHostToDevice);
saxpy<<< N/128, 128 >>>(N, 3.0, d_x, d_y);
cudaMemcpy(y, d_y, size, cudaMemcpyDeviceToHost);
...
SAXPY (Y=A*X+Y)
CPU CUDA
void saxpy(int n, float a,
float *x, float *y)
{
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
16
Pascal GPUs
17
Perf
orm
ance /
W
2012 20142008 2010 2016 2018
GPUロードマップ
TeslaFermi
Kepler
Maxwell
Pascal
Volta
18NVIDIA CONFIDENTIAL. DO NOT DISTRIBUTE.
TESLA (PASCAL世代)
TESLA P4TESLA P40TESLA P100
(PCI)
科学技術計算
GP100
Deep Learning
(トレーニング)
GP102
Deep Learning
(インファレンス)
GP104
TESLA P100(SXM2)
科学技術計算
GP100
19
TESLA P100世界最速の計算ノードを実現する最新GPUアーキテクチャ
Pascalアーキテクチャ NVLinkHBM2スタックメモリ Page Migration Engine
PCIe
Switch
PCIe
Switch
CPU CPU
高い演算能力 高速なシステム・インタコネクト高いメモリバンド幅 シンプルなプログラミング
Unified Memory
CPU
Tesla P100
20
GP100
56 SMs
3584 CUDA Cores
5.3 TF – fp64
10.6 TF – fp32
21.2 TF – fp16
SM (Stream Multiprocessor)
21
GP100 SM
GP100
CUDAコア 64
レジスタ 256 KB
共有メモリ 64 KB
Activeスレッド 2048
Activeワープ 64
22
HBM2 : 732GB/sメモリ容量:16GB、ECCはHW実装
23
Unified Memory on PascalKepler/Maxwell世代GPUから改善
▪ Unified Memoryの特徴
▪ CPUとGPU間のデータ移動、ユーザは明示的に指示しなくてよい
▪ Pascalからの改善点
▪ On-demandでページを移動 (Pascal Page Migration Engine)
▪ GPUメモリ容量を超えるデータ (Over-Subscription, Out-of-Core)
Unified Memory
CPU
Tesla P100
24
NVLINK
• P100 supports 4 NVLinks
• 20+20 GB/s per link
• Up to 94% bandwidth efficiency
• Links can be ganged for higher bandwidth
NVLinkon Tesla P100
20+20 GB/s
20+20 GB/s
20+20 GB/s
20+20 GB/s
P100 P100High speed interconnect
25
TSUBAME3 Compute Node
• GPU: Tesla P100
• 4 GPUs /node
• Fully connected by NVLink
(*) https://www.slideshare.net/NVIDIAJapan/hpc-ai-tsubame30-abci
26
ピーク性能: K20x vs. P100
K20x P100
CUDA cores 2688 3584
Clock speed (GHz) 0.73 1.48
TFLOPS (SP, fp32) 3.9 10.6
TFLOPS (DP, fp64) 1.3 5.3
Memory GDDR5 - 6GB HBM2 – 16GB
Bandwidth (GB/s) 250 730
27
実効性能: K40 vs. P100
28
GPUs after Pascal
29
VOLTA AND TURING
For HPC and Deep Learning
Pascalから進化、多くの機能を共有
Tesla P100 (GP100) QUADRO P6000 (GP102)
Volta (cc70)
For Graphics and Deep Learning
Turing (cc75)
Tesla V100(GV100)
QUADRO RTX6000(TU102)
30
VOLTAの概要
HPCとDeep Learning、両方に最適なGPU
Volta Architecture
Most Productive GPU
Tensor Core
125 Programmable
TFLOPS Deep Learning
Improved SIMT Model
New Algorithms
Volta MPS
Inference Utilization
Improved NVLink &
HBM2
Efficient Bandwidth
31
NVIDIA TURING: GRAPHICS REINVENTED
RTコア TENSORコア
ディープラーニング高速化
リアルタイムレイトレーシング
進化したプログラマブルシェーダー
STREAMING MULTIPROCESSOR
TURINGの概要
32
INTRODUCING CUDA 10.0
New GPU Architecture, Tensor Cores, NVSwitch Fabric
TURING AND NEW SYSTEMSCUDA Graphs, Vulkan & DX12 Interop, Warp Matrix
CUDA PLATFORM
GPU-accelerated hybrid JPEG decoding,Symmetric Eigenvalue Solvers, FFT Scaling
LIBRARIESNew Nsight Products – Nsight Systems and Nsight Compute
DEVELOPER TOOLS
Scientific Computing
33
OpenACC
34
アプリをGPU対応する方法
Application
Library
GPU対応ライブラリにチェンジ
簡単に開始
CUDAOpenACC
主要処理をCUDAで記述
高い自由度既存コードにディレクティブを挿
入
簡単に加速
35
OPENACC
Program myscience
... serial code ...
!$acc kernels
do k = 1,n1
do i = 1,n2
... parallel code ...
enddo
enddo
!$acc end kernels
... serial code …
End Program myscience
CPU
GPU
既存のC/Fortranコード
簡単: 既存のコードにコンパイラへのヒントを追加
強力: 相応の労力で、コンパイラがコードを自動で並列化
オープン: 複数コンパイラベンダが、様々なプロセッサをサポート
NVIDIA GPU, AMD GPU,
Intel CPU, Intel メニコア(予定)
ヒントの追加
36
GPUコンピューティング
アプリケーション・コード
GPU
CPU
並列部分はGPUで実行
計算の重い部分
逐次部分はCPU上で実行
Do i=1,N
End do
OpenACC
37
void saxpy(int n,
float a,
float *x,
float *restrict y)
{
#pragma acc parallel copy(y[:n]) copyin(x[:n])
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
SAXPY (y=a*x+y)
▪ omp → acc ▪ データの移動
OpenMP OpenACC
void saxpy(int n,
float a,
float *x,
float *restrict y)
{
#pragma omp parallel for
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
38
subroutine saxpy(n, a, X, Y)
real :: a, Y(:), Y(:)
integer :: n, i
!$acc parallel copy(Y(:)) copyin(X(:))
do i=1,n
Y(i) = a*X(i)+Y(i)
enddo
!$acc end parallel
end subroutine saxpy
...
call saxpy(N, 3.0, x, y)
...
SAXPY (y=a*x+y, FORTRAN)
▪ FORTRANも同様
OpenMP OpenACC
subroutine saxpy(n, a, X, Y)
real :: a, X(:), Y(:)
integer :: n, i
!$omp parallel do
do i=1,n
Y(i) = a*X(i)+Y(i)
enddo
!$omp end parallel do
end subroutine saxpy
...
call saxpy(N, 3.0, x, y)
...
39
void saxpy(int n, float a,
float *x,
float *restrict y)
{
#pragma acc parallel copy(y[:n]) copyin(x[:n])
for (int i = 0; i < n; ++i) {
y[i] += a*x[i];
}
}
...
saxpy(N, 3.0, x, y);
...
OPENACC: PARALLEL DIRECTIVE
並列化領域を指示する
40
void saxpy(int n, float a,
float *x,
float *restrict y)
{
#pragma acc kernels copy(y[:n]) copyin(x[:n])
for (int i = 0; i < n; ++i) {
y[i] += a*x[i];
}
}
...
saxpy(N, 3.0, x, y);
...
OPENACC: KERNELS DIRECTIVE
並列化領域を指示する
Parallel: ユーザ主導
Kernels: コンパイラ主導
41
void saxpy(int n, float a,
float *x,
float *restrict y)
{
#pragma acc parallel copy(y[:n]) copyin(x[:n])
#pragma acc loop independent
for (int i = 0; i < n; ++i) {
y[i] += a*x[i];
}
}
...
saxpy(N, 3.0, x, y);
...
OPENACC: LOOP CLAUSE
ループの並列化方法を指示する
independent: 並列化可能
seq: 逐次実行
collapse: ループ融合
gang/vector: 並列化粒度
...
42
void saxpy(int n, float a,
float *x,
float *restrict y)
{
#pragma acc parallel copy(y[:n]) copyin(x[:n])
for (int i = 0; i < n; ++i) {
y[i] += a*x[i];
}
}
...
saxpy(N, 3.0, x, y);
...
OPENACC: DATA CLAUSE
データの移動方法を指示する
copyin: CPU → GPU
copyout: CPU GPU
copy: (両方)
create: (メモリ確保)
...
43
void saxpy(int n, float a,
float *x,
float *restrict y)
{
#pragma acc parallel present(x, y)
for (int i = 0; i < n; ++i) {
y[i] += a*x[i];
}
}
...
#pragma acc data copy(y[:N]) copyin(x[:N])
{
saxpy(N, 3.0, x, y);
}
...
OPENACC DATA DIRECTIVE
データ領域を指示する
44
OPENMP と OPENACC の併用
void saxpy(int n, float a,
float *x,
float *restrict y)
{
#pragma acc parallel copy(y[:n]) copyin(x[:n])
#pragma omp parallel for
for (int i = 0; i < n; ++i) {
y[i] += a*x[i];
}
}
...
saxpy(N, 3.0, x, y);
...
45
簡単にコンパイル
OpenMP / OpenACC
void saxpy(int n, float a,
float *x,
float *restrict y)
{
#pragma acc parallel copy(y[:n]) copyin(x[:n])
#pragma omp parallel for
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
$ pgcc -acc –Minfo=acc –ta=tesla saxpy.csaxpy:
16, Generating present_or_copy(y[:n])
Generating present_or_copyin(x[:n])
Generating Tesla code
19, Loop is parallelizable
Accelerator kernel generated
19, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
46
簡単に実行
OpenMP / OpenACC
void saxpy(int n, float a,
float *x,
float *restrict y)
{
#pragma acc parallel copy(y[:n]) copyin(x[:n])
#pragma omp parallel for
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
$ pgcc -acc –Minfo=acc –ta=tesla saxpy.csaxpy:
16, Generating present_or_copy(y[:n])
Generating present_or_copyin(x[:n])
Generating Tesla code
19, Loop is parallelizable
Accelerator kernel generated
19, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
$ nvprof ./a.out ==10302== NVPROF is profiling process 10302, command: ./a.out
==10302== Profiling application: ./a.out
==10302== Profiling result:
Time(%) Time Calls Avg Min Max Name
62.95% 3.0358ms 2 1.5179ms 1.5172ms 1.5186ms [CUDA memcpy HtoD]
31.48% 1.5181ms 1 1.5181ms 1.5181ms 1.5181ms [CUDA memcpy DtoH]
5.56% 268.31us 1 268.31us 268.31us 268.31us saxpy_19_gpu
47
OPENACCが加速する科学技術計算
48
Janus Juul Eriksen, PhD Fellow
qLEAP Center for Theoretical Chemistry, Aarhus University
“
OpenACC makes GPU computing approachable for
domain scientists. Initial OpenACC implementation
required only minor effort, and more importantly,
no modifications of our existing CPU implementation.
“
LSDALTON
Large-scale application for calculating high-accuracy molecular energies
Lines of Code
Modified
# of Weeks
Required
# of Codes to
Maintain
<100 Lines 1 Week 1 Source
Big Performance
7.9x8.9x
11.7x
ALANINE-113 ATOMS
ALANINE-223 ATOMS
ALANINE-333 ATOMS
Speedup v
s C
PU
Minimal Effort
LS-DALTON CCSD(T) ModuleBenchmarked on Titan Supercomputer (AMD CPU vs Tesla K20X)
https://developer.nvidia.com/openacc/success-stories
49
Brad Sutton, Associate Professor of Bioengineering and
Technical Director of the Biomedical Imaging Center
University of Illinois at Urbana-Champaign
“Now that we’ve seen how easy it is to program the
GPU using OpenACC and the PGI compiler, we’re
looking forward to translating more of our projects
“
CHALLENGE• Produce detailed and accurate brain images by applying
computationally intensive algorithms to MRI data
• Reduce reconstruction time to make diagnostic use possible
SOLUTION• Accelerated MRI reconstruction application with OpenACC
using NVIDIA GPUs
RESULTS• Reduced reconstruction time for a single high-resolution MRI
scan from 40 days to a couple of hours
• Scaled on Blue Waters at NCSA to reconstruct 3000 images in
under 24 hours
POWERGRIDAdvanced MRI Reconstruction Model
https://developer.nvidia.com/openacc/success-stories
50
“
OpenACC enabled us to
target routines for GPU
acceleration without
rewriting code, allowing us
to maintain portability on a
code that is 20-years old
“
David Gutzwiller, Head of HPC
NUMECA International
CHALLENGE• Accelerate 20 year old highly optimized code
on GPUs
SOLUTION• Accelerated computationally intensive routines
with OpenACC
RESULTS• Achieved 10x or higher speed-up on key
routines
• Full app speedup of up to 2x on the Oak Ridge
Titan supercomputer
• Total time spent on optimizing various routines
with OpenACC was just five person-months
NUMECA FINE/TURBOCommercial CFD Application
https://developer.nvidia.com/openacc/success-stories
51
The most significant result from
our performance studies is faster
computation with less energy
consumption compared with our
CPU-only runs.
Dr. Misun Min, Computation Scientist
Argonne National Laboratory
CHALLENGE• Enable NekCEM to deliver strong scaling on
next-generation architectures while
maintaining portability
SOLUTION• Use OpenACC to port the entire program
to GPUs
RESULTS• 2.5x speedup over a highly tuned CPU-only
version
• GPU used only 39 percent of the energy
needed by 16 CPUs to do the same
computation in the same amount of time
NEKCEMComputational Electromagnetics Application
“
“
https://developer.nvidia.com/openacc/success-stories
52
Adam Jacobs, PhD candidate in the Department of Physics and
Astronomy at Stony Brook University
On the reactions side, accelerated calculations allow us to model larger
networks of nuclear reactions for similar computational costs as the
simple networks we model now
MAESTRO & CASTROAstrophysics 3D Simulation
““
CHALLENGE• Pursuing strong scaling and portability to run
code on GPU-powered supercomputers
SOLUTION• OpenACC compiler on OLCF’s Titan
supercomputer
RESULTS• 4.4x faster reactions than on a multi-core
computer with 16 cores
• Accelerated calculations allow modeling larger
networks of nuclear reactions for similar
computational costs as simple networks
2 weeks to learn OpenACC
2 weeks to modify code
https://developer.nvidia.com/openacc/success-stories
53
Wayne Gaudin and Oliver Perks
Atomic Weapons Establishment, UK
We were extremely impressed that we can run OpenACC on a CPU with
no code change and get equivalent performance to our OpenMP/MPI
implementation.
CLOVERLEAFPerformance Portability for a Hydrodynamics Application
Sp
ee
du
p v
s 1
CP
U C
ore
Benchmarked Intel(R) Xeon(R) CPU E5-2690 v2 @ 3.00GHz, Accelerator: Tesla K80
““
CHALLENGE• Application code that runs across architectures
without compromising on performance
SOLUTION• Use OpenACC to port the CloverLeaf mini app
to GPUs and then recompile and run the same
source code on multi-core CPUs
RESULTS• Same performance as optimized OpenMP
version on x86 CPU
• 4x faster performance using the same code on
a GPU
https://developer.nvidia.com/openacc/success-stories
54
Lixiang Luo, Researcher
Aerospace Engineering Computational Fluid Dynamics Laboratory
North Carolina State University (NCSU)
“
OpenACC is a highly effective tool for programming fully
implicit CFD solvers on GPU to achieve true 4X speedup“
* CPU Speedup on 6 cores of Xeon E5645, with additional cores performance reduces due to partitioning and MPI overheads
CHALLENGE• Accelerate a complex implicit CFD solver on GPU
SOLUTION• Used OpenACC to run solver on GPU with
minimal code changes.
RESULTS• Achieved up to 4X speedups on Tesla GPU over
parallel MPI implementation on x86 multicore
processor
• Structured approach to parallelism provided by
OpenACC allowed better algorithm design
without worrying about GPU architecture
INCOMP3D3D Fully Implicit CFD Solver
https://developer.nvidia.com/openacc/success-stories
55
Earthquake Simulation (理研、東大地震研)
▪ WACCPD 2016(SC16併催WS): Best Paper Award
http://waccpd.org/wp-content/uploads/2016/04/SC16_WACCPD_fujita.pdfより引用
56
NICAM
▪ 気象・気候モデル by 理研AICS/東大▪ 膨大なコード (数十万行)
▪ ホットスポットがない (パレートの法則)
▪ 特性の異なる2種類の処理▪ 力学系 … メモリバンド幅ネック
▪ 物理系 … 演算ネック
57
NICAM: 力学系(NICAM-DC)
▪ OpenACCによるGPU化▪ 主要サブルーチンは、全てGPU上で動作(50以上)
▪ MPI対応済み
▪ 2週間
▪ 良好なスケーラビリティ▪ Tsubame 2.5, 最大2560
GPUs
▪ Scaling factor: 0.8
Weak scaling
1.E+01
1.E+02
1.E+03
1.E+04
1.E+05
1.E+00 1.E+01 1.E+02 1.E+03 1.E+04Perf
orm
ance (
GFLO
PS)
Number of CPUs or GPUs
Tsubame 2.5 (GPU:K20X)
K computer
Tsubame 2.5 (CPU:WSM)
(*) weak scaling
Courtesy of Dr. Yashiro from RIKEN AICS
58
NICAM: 物理系(SCALE-LES)
▪ Atmospheric radiation transfer
▪ 物理系の中で、最も重い計算
▪ OpenACCによるGPU対応済
1.00 1.99 3.88 8.51
37.8
76.0
151
0
20
40
60
80
100
120
140
160
1 core 2 core 4 core 10 core 1 GPU 2 GPUs 4 GPUs
Xeon E5-2690v2(3.0GHz,10-core) Tesla K40
Speedup
vs.
CPU
1-c
ore
(*) PCIデータ転送時間込み, グリッドサイズ:1256x32x32
Better
59
SEISM3D
▪ 地震シミュレーション by 古村教授(東大地震研)
▪ 主要サブルーチンのGPU対応が完了▪ メモリバンド幅ネック、 3次元モデル(2次元分割)、隣接プロセス間通信
605
459
134
0
100
200
300
400
500
600
K: 8x SPARC64VIIIfx
CPU: 8x XeonE5-2690v2
GPU: 8x TeslaK40
Tim
e (
sec)
SEISM3D (480x480x1024, 1K steps)
3.4x speedup
(アプリ全体)
0
20
40
60
80
100
120
140
GPU: 8x Tesla K40
Others (CPU, MPI and so on)
[CUDA memcpy DtoH]
[CUDA memcpy HtoD]
(other subroutines)
update_vel_pml
update_vel
update_stress_pml
update_stress
diff3d_*
GPUの実行時間内訳
Better
60
CM-RCM IC-CG
▪ IC-CG法のベンチマークコード by 中島教授(東大)▪ CM-RCM法(Cyclic Multi-coloring Reverse Cuthill-Mckee)を使用
▪ メインループ内のサブルーチンを全てOpenACCでGPU化
3.36
1.58 1.53 1.39
0.655
0
1
2
3
4
OpenMP OpenMP OpenMP OpenMP OpenACC
Opteron 6386SE(2.8GHz,16core)
SPARC64 Ixfx(1.85GHz,16core)
Xeon E5-2680v2(2.8GHz,10core)
Xeon-Phi 5110P Tesla K40
Tim
e (
second)
CM-RCM ICCG (100x100x100)
Better
Courtesy of Dr. Ohshima from U-Tokyo
61
CCS-QCD
▪ QCDコード by 石川准教授(広島大)
▪ BiCGStab計算を全てOpenACCでGPU化▪ データレイアウトを変更: AoS → SoA
32.324.3 22.1 20.9 19.7
42.5
53.357.9 60.8 63.4
0
10
20
30
40
50
60
70
80
90
8x8x8x32 8x8x8x64 8x8x16x64 8x16x16x64 16x16x16x64
GFLO
PS
Problem Size
CCS-QCD: BiCGStab Total FLOPS
Xeon E5-2690v2(3.0GHz,10core,OpenMP) Tesla K40(OpenACC)Better
62
CUDA
63
CUDAプログラミング
▪ プログラミングモデル
▪ アーキテクチャ
▪ 性能Tips
64
GPUコンピューティング
▪ 高スループット指向のプロセッサ
▪ 分離されたメモリ空間
GPU Memory
CPU Memory
PCI
CPU GPU
65
GPUプログラム
__global__ void saxpy(int n, float a,
float *x, float *y)
{
int i = threadIdx.x + blodkDim.x * blockIdx;
if (i < n)
y[i] += a*x[i];
}
...
size_t size = sizeof(float) * N;
cudaMemcpy(d_x, x, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_y, y, size, cudaMemcpyHostToDevice);
saxpy<<< N/128, 128 >>>(N, 3.0, d_x, d_y);
cudaDeviceSynchronize();
cudaMemcpy(y, d_y, size, cudaMemcpyDeviceToHost);
...
void saxpy(int n, float a,
float *x, float *y)
{
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
CPU GPU
66
GPU実行の基本的な流れ
▪ GPUは、CPUからの制御で動作
▪ 入力データ: CPUからGPUに転送 (H2D)
▪ GPUカーネル: CPUから投入
▪ 出力データ: GPUからCPUに転送 (D2H)
CPU GPU
入力データ転送
GPUカーネル投入
同期
出力データ転送
GPU上で演算
67
GPUプログラム
__global__ void saxpy(int n, float a,
float *x, float *y)
{
int i = threadIdx.x + blodkDim.x * blockIdx;
if (i < n)
y[i] += a*x[i];
}
...
size_t size = sizeof(float) * N;
cudaMemcpy(d_x, x, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_y, y, size, cudaMemcpyHostToDevice);
saxpy<<< N/128, 128 >>>(N, 3.0, d_x, d_y);
cudaDeviceSynchronize();
cudaMemcpy(y, d_y, size, cudaMemcpyDeviceToHost);
...
void saxpy(int n, float a,
float *x, float *y)
{
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
CPU GPU
入力データ転送
カーネル起動
同期
出力データ転送
68
GPUプログラム (Unified Memory)
__global__ void saxpy(int n, float a,
float *x, float *y)
{
int i = threadIdx.x + blodkDim.x * blockIdx;
if (i < n)
y[i] += a*x[i];
}
...
saxpy<<< N/128, 128 >>>(N, 3.0, x, y);
cudaDeviceSynchronize();
...
void saxpy(int n, float a,
float *x, float *y)
{
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
CPU GPU
カーネル起動
同期
69
GPUプログラム (Unified Memory)
__global__ void saxpy(int n, float a,
float *x, float *y)
{
int i = threadIdx.x + blodkDim.x * blockIdx;
if (i < n)
y[i] += a*x[i];
}
...
int dev_id = 0;
size_t size = sizeof(float) * N;
cudaMemPrefetchAsync(x, size, dev_id);
cudaMemPrefetchAsync(y, size, dev_id);
saxpy<<< N/128, 128 >>>(N, 3.0, x, y);
cudaDeviceSynchronize();
...
void saxpy(int n, float a,
float *x, float *y)
{
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
CPU GPU
プリフェッチ
70
GPUカーネル
▪ GPUカーネル: 1つのGPUスレッドの処理内容を記述▪ 基本: 1つのGPUスレッドが、1つの配列要素を担当
__global__ void saxpy(int n, float a,
float *x, float *y)
{
int i = threadIdx.x + blodkDim.x * blockIdx.x;
if (i < n)
y[i] += a*x[i];
}
...
saxpy<<< N/128, 128 >>>(N, 3.0, d_x, d_y);
...
void saxpy(int n, float a,
float *x, float *y)
{
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, x, y);
...
CPU GPU
Global スレッドID
71
Execution Configuration(ブロック数とブロックサイズ)
__global__ void saxpy(int n, float a,
float *x, float *y)
{
int i = threadIdx.x + blodkDim.x * blockIdx.x;
if (i < n)
y[i] += a*x[i];
}
...
saxpy<<< N/128, 128 >>>(N, 3.0, d_x, d_y);
...
ブロック数 ブロックサイズ
ブロック数 x ブロックサイズ = 配列要素数
スレッドIDブロックID
ブロックサイズ
72
スレッド階層(スレッド、ブロック、グリッド)
グリッド
x[] 0 127 128 255
y[] 0 127 128 255
y[i] = a*x[i] + y[i]
256 383 384
256 383 384
ブロック2ブロック1ブロック0 ブロック
スレッド(global)
0 127 128 255 256 383 384
▪ ブロックサイズ(スレッド数/ブロック)は、カーネル毎に設定可能▪ 推奨: 128 or 256 スレッド
スレッド(local)
0 127 0 127 0 127 0
73
Execution Configuration(ブロック数とブロックサイズ)
__global__ void saxpy(int n, float a,
float *x, float *y)
{
int i = threadIdx.x + blodkDim.x * blockIdx.x;
if (i < n)
y[i] += a*x[i];
}
...
saxpy<<< N/128, 128 >>>(N, 3.0, d_x, d_y);
...
ブロック数 ブロックサイズ
ブロック数 x ブロックサイズ = 配列要素数
N/ 64, 64N/256, 256
74
2D配列のGPUカーネル例
▪ ブロックサイズ(ブロック形状)は、1D~3Dで表現可能
__global__ void MatAdd(float A[N][N], float B[N][N], float C[N][N])
{
int i = threadIdx.x + blodkDim.x * blockIdx.x;
int j = threadIdx.y + blodkDim.y * blockIdy.y;
if ( i < N && j < N )
C[i][i] = A[i][j] + B[i][j];
}
...
dim3 sizeBlock( 16, 16 );
dim3 numBlocks( N/sizeBlock.x, N/sizeBlock.y );
MatAdd<<< numBlocks, sizeBlock >>>(A, B, C);
...
32, 864, 4
Globalスレッド ID (x)
GlobalスレッドID (y)
ブロックサイズ (x,y)
ブロック数 (x,y)
75
ブロック・マッピング、スレッド・マッピング
dim3 sizeBlock(16,16)
(0,0) (1,0) (2,0)
(0,1) (1,1) (2,1)
(0,2) (1,2) (2,2)
ブロックID(blockIdx)
dim3 sizeBlock(32,8)
(0,0) (1,0)
(0,1) (1,1)
(0,2) (1,2)
(0,3) (1,3)
(0,4) (1,4)
(0,0)
(15,15)
(0,0)
(31,7)
スレッドID(threadIdx)
76
CUDAプログラミング
▪ プログラミングモデル
▪ アーキテクチャ
▪ 性能Tips
77
GPUアーキテクチャ概要
▪ PCI I/F▪ ホスト接続インタフェース
▪ Giga Thread Engine▪ SMに処理を割り振るスケジューラ
▪ DRAM I/F (HBM2)▪ 全SM、PCI I/Fからアクセス可能なメモリ (デバイスメモリ, フレームバッファ)
▪ L2 cache (4MB)▪ 全SMからアクセス可能なR/Wキャッシュ
▪ SM (Streaming Multiprocessor)▪ 「並列」プロセッサ、GP100:最多60
Pascal GP100
78
SM (Stream Multi-Processor)
▪ CUDAコア▪ GPUスレッドはこの上で動作
▪ GP100: 64個 /SM
▪ Other units▪ LD/ST, SFU, etc
▪ レジスタ(32bit): 64K個
▪ 共有メモリ: 64KB
▪ Tex/L1キャッシュPascal GP100
79
GPUカーネル実行の流れ
▪ CPUが、GPUに、グリッドを投入▪ 具体的な投入先は、Giga Thread Engine
グリッド
ブロック
ブロック
スレッド
スレッド
80
GPUカーネル実行の流れ
▪ Giga Thread Engine(GTE)が、SMに、ブロックを投入▪ GTEは、ブロックスケジューラ
▪ グリッドをブロックに分解して、ブロックを、空いているSMに割当てる
グリッド
ブロック
ブロック
スレッド
スレッド
81
ブロックをSMに割り当て
▪ 各ブロックは、互いに独立に実行▪ ブロック間では同期しない、実行順序の保証なし
▪ 1つのブロックは複数SMにまたがらない▪ 1つのSMに、複数ブロックが割当てられることはある
グリッド
ブロック
ブロック
ブロック
ブロック
82
GPUカーネル実行の流れ
▪ SM内のスケジューラが、スレッドをCUDAコアに投入
グリッド
ブロック
ブロック
スレッド
スレッド
83
GPUカーネル実行の流れ
▪ SM内のスケジューラが、ワープをCUDAコアに投入▪ ワープ: 32スレッドの塊
▪ ブロックをワープに分割、実行可能なワープを、空CUDAコアに割当てる
グリッド
ブロック
ブロック
ワープ
ワープ
84
ワープのCUDAコアへの割り当て
▪ ワープ内の32スレッドは、同じ命令を同期して実行
▪ 各ワープは、互いに独立して実行▪ 同じブロック内のワープは、明示的に同期可能(__syncthreads())
グリッド
ブロック
ブロック
ワープ
ワープ
ワープ
SIMT(Single Instruction Multiple Threads)
ワープ
85
GPUアーキの変化を問題としないプログラミングモデル
Kepler, CC3.5
192 cores /SM
Pascal, CC6.0
64 cores /SM
Maxwell, CC5.0
128 cores /SM
86
CUDAプログラミング
▪ プログラミングモデル
▪ アーキテクチャ
▪ 性能Tips
87
リソース使用率 (Occupancy)
SMの利用効率を上げる≒ SMに割当て可能なスレッド数を、
上限に近づける
▪ レジスタ使用量(/スレッド)▪ できる限り減らす
▪ DP(64bit)は、2レジスタ消費
▪ レジスタ割り当て単位は8個
▪ レジスタ使用量と、割当て可能なスレッド数の関係▪ 32レジスタ: 2048(100%), 64レジスタ: 1024(50%)
▪ 128レジスタ:512(25%), 256レジスタ: 256(12.5%)
CUDAコア数: 64最大スレッド数: 2048最大ブロック数: 32共有メモリ: 64KB
レジスタ数(32-bit): 64K個
リソース量/SM (GP100)
88
リソース使用率 (Occupancy)
SMの利用効率を上げる≒ SMに割当て可能なスレッド数を、上限に近づける
▪ スレッド数(/ブロック)▪ 64以上にする▪ 64未満だと最大ブロック数がネックになる
▪ 共有メモリ使用量(/ブロック)▪ できる限り減らす▪ 共有メモリ使用量と、割当て可能なブロック数の関係
▪ 32KB:2ブロック, 16KB:4ブロック, 8KB:8ブロック
CUDAコア数: 64最大スレッド数: 2048最大ブロック数: 32共有メモリ: 64KB
レジスタ数(32-bit): 64K個
リソース量/SM (GP100)
89
リソース使用率 (Occupancy)
空き時間を埋める
▪ CUDAストリーム (≒キュー)▪ 同じCUDAストリームに投入した操作: 投入順に実行
▪ 別のCUDAストリームに投入した操作: 非同期に実行 (オーバラップ実行)
(*) 操作: GPUカーネル, データ転送
[CUDAストリームの効果例]
GPUカーネルとデータ転送が
オーバラップして同時に実行されている
90
デバイスメモリへのアクセスは、まとめて
▪ コアレス・アクセス▪ 32スレッド(ワープ)のロード/ストアをまとめて、メモリトランザクションを発行▪ トランザクションサイズ: 32B, 64B or 128B
▪ トランザクション数は、少ないほど良い配列 128B境界 128B境界
0 1 2 29 30 31283
0 1 14 17 30 311615
0 1 2
Best
Good
Bad
128B x1
64B x2
32B x32
91
分岐を減らす
▪ ワープ内のスレッドが別パスを選択すると遅くなる▪ ワープ内のスレッドは、命令を共有 (SIMT)
▪ ワープ内のスレッドが選んだ全パスの命令を実行
▪ あるパスの命令を実行中、そのパスにいないスレッドはinactive状態
▪ Path divergenceを減らす▪ できる限り、同ワープ内のスレッドは
同じパスを選択させる
A[id] > 0
処理 X
処理 Y
true false
01
23
92
まとめ
▪ GPU Computing
▪ Pascal GPUs (Tesla P100)
▪ OpenACC
▪ CUDA
93
GPU HACKATHONShttps://www.olcf.ornl.gov/for-users/training/gpu-hackathons/
HANDS-ON (CUDA)
2
CUDA TOOLKIT DOCUMENTATIONhttp://docs.nvidia.com/cuda/index.html
Programming
Guide
CUDA Runtime
API
3
DAXPY
//
// daxpy: y[i] = a * x[i] + y[i]
//
void daxpy(int n, double a, double *x, double *y)
{
int i;
for (i = 0; i < n; i++) {
y[i] += a*x[i];
}
}
Y[i] = A * X[i] + Y[i]
4
4つのタスク
Task1: 配列をUnified Memoryで確保する
Task2: CUDAカーネルを実行できるようにする
Task3: Unified Memory上のデータの移動を指示する
Task4: CPUとGPU間で明示的にデータを確保・移動する
5
ディレクトリ構成、進め方
reference … リファレンスCPUコード
task1 … タスク1
task1-solution … タスク1の答え
task2 … タスク2
task2-solution … タスク2の答え
task3 … タスク3
task3-solution … タスク3の答え
task4 … タスク4
task4-solution … タスク4の答え
タスクの進め方
• ソース・ファイル (daxpy.cu) の中の/* TODO: */ の部分を修正して、正しく動作するようにする
6
TASK0
$ newgrp tgz-gpu-training-2017
$ cd reference
$ module load cuda
$ make
$ qsub –g tgz-training –ar 4170 ./batch.sh
Your job **** ("batch.sh") has been submitted
$ qstat
$ ls batch.sh.*
batch.sh.e**** batch.sh.o****
ビルド & ジョブ投入
#!/bin/sh
#$ -cwd
#$ -l q_node=1
#$ -l h_rt=0:10:00
. /etc/profile.d/modules.sh
module load cuda
./daxpy
batch.sh
7
TASK1
Unified Memoryでメモリを確保する
• cudaMallocManaged ( void** ptr, size_t size )
ptr 確保するメモリのポインタ
size 確保するメモリサイズ (バイト)
配列をUnified Memoryで確保する
メモリを解放する
• cudaFree ( void* ptr )
ptr 解放するメモリのポインタ
8
TASK2
CUDAカーネル内で使用できる定義済み変数
• threadIdx.x … スレッドブロック内の、そのスレッドのID (x軸)
• blockIdx.x … そのスレッドがいる、スレッドブロックのID (x軸)
• blockDim.x … スレッドブロックの大きさ (x軸)
CUDAカーネルを実行できるようにする
GPUの実行完了を待つ
• cudaDeviceSynchronize ( void )
カーネル実行条件
• cuda_kernel<<<ブロック数, スレッド数>>>( ... )
• ブロック数 * スレッド数 ≧ 配列サイズ
9
GPUは使われている?
$ nvprof ./daxpy==17994== NVPROF is profiling process 17994, command: ./daxpy==17994== Profiling application: ./daxpy==17994== Profiling result:
Type Time(%) Time Calls Avg Min Max NameGPU activities: 100.00% 5.7737ms 1 5.7737ms 5.7737ms 5.7737ms cuda_daxpy(int, double, double*, double*)
API calls: 96.98% 261.73ms 2 130.87ms 558.90us 261.17ms cudaMallocManaged2.14% 5.7810ms 1 5.7810ms 5.7810ms 5.7810ms cudaDeviceSynchronize0.36% 981.18us 2 490.59us 489.25us 491.94us cudaFree0.30% 805.37us 188 4.2830us 132ns 174.78us cuDeviceGetAttribute0.15% 402.87us 2 201.44us 174.83us 228.04us cuDeviceTotalMem0.03% 81.344us 1 81.344us 81.344us 81.344us cudaLaunch0.03% 70.161us 2 35.080us 33.427us 36.734us cuDeviceGetName0.00% 8.0070us 4 2.0010us 155ns 6.7440us cudaSetupArgument0.00% 4.3600us 1 4.3600us 4.3600us 4.3600us cudaConfigureCall0.00% 2.8580us 3 952ns 148ns 2.2840us cuDeviceGetCount0.00% 1.3850us 4 346ns 193ns 581ns cuDeviceGet
==17994== Unified Memory profiling result:Device "Quadro GP100 (0)"
Count Avg Size Min Size Max Size Total Size Total Time Name403 40.654KB 4.0000KB 984.00KB 16.00000MB 3.135008ms Host To Device96 170.67KB 4.0000KB 0.9961MB 16.00000MB 2.571456ms Device To Host26 - - - - 6.493536ms Gpu page fault groups
Total CPU Page faults: 96
プロファイラー(nvprof)で確認する
10
TASK3Unified Memory上のデータの移動を指示する
Unified Memory上のデータを、指定GPU/CPUにプリフェッチする
• cudaMemPrefetchAsync ( void* ptr, size_t size, int dstDevice )
ptr Unified Memoryで確保したメモリのポインタ
size プリフェッチサイズ (バイト)
dstDevice プリフェッチ先
0以上 … 指定番号のGPUにデータをプリフェッチ
cudaCpuDeviceId … CPUにデータをプリフェッチ
11
CUDAカーネルの実行時間はどうなる?
$ nvprof ./daxpy==23419== NVPROF is profiling process 23419, command: ./daxpyOK==23419== Profiling application: ./daxpy==23419== Profiling result:
Type Time(%) Time Calls Avg Min Max NameGPU activities: 100.00% 46.112us 1 46.112us 46.112us 46.112us cuda_daxpy(int, double, double*, double*)
API calls: 97.47% 281.82ms 2 140.91ms 386.06us 281.44ms cudaMallocManaged0.95% 2.7416ms 3 913.87us 170.27us 1.4335ms cudaMemPrefetchAsync0.79% 2.2785ms 1 2.2785ms 2.2785ms 2.2785ms cudaDeviceSynchronize0.31% 909.02us 2 454.51us 408.69us 500.33us cudaFree0.28% 808.30us 188 4.2990us 135ns 175.31us cuDeviceGetAttribute0.14% 403.31us 2 201.66us 174.94us 228.38us cuDeviceTotalMem0.03% 77.600us 1 77.600us 77.600us 77.600us cudaLaunch0.02% 71.052us 2 35.526us 33.959us 37.093us cuDeviceGetName0.00% 9.7600us 4 2.4400us 168ns 8.5690us cudaSetupArgument0.00% 2.8240us 3 941ns 221ns 2.1960us cuDeviceGetCount0.00% 1.8710us 1 1.8710us 1.8710us 1.8710us cudaConfigureCall0.00% 1.4120us 4 353ns 187ns 614ns cuDeviceGet
==23419== Unified Memory profiling result:Device "Quadro GP100 (0)"
Count Avg Size Min Size Max Size Total Size Total Time Name8 2.0000MB 2.0000MB 2.0000MB 16.00000MB 2.816864ms Host To Device
52 315.08KB 4.0000KB 2.0000MB 16.00000MB 2.577088ms Device To HostTotal CPU Page faults: 72
プロファイラー(nvprof)で確認する
12
TASK4CPUとGPU間で明示的にデータを確保・移動する
デバイスメモリを確保する
• cudaMalloc ( void** ptr, size_t size )
ptr 確保するメモリのポインタ
size 確保するメモリサイズ (バイト)
CPUとGPU間でデータをコピー(移動)する
• cudaMemcpy ( void* dst, void* src, size_t size, cudaMemcpyKind kind )
dst コピー先メモリのポインタ
src コピー元メモリのポインタ
size コピーサイズ (バイト)
kind 移動方向
cudaMemcpyHostToDevice … CPUからGPUにコピー
cudaMemcpyDeviceToHost … GPUからCPUにコピー
メモリを解放する
• cudaFree ( void* ptr )
ptr 解放するメモリのポインタ
13
データはどう転送される?
$ nvprof ./daxpy==18069== NVPROF is profiling process 18069, command: ./daxpyOK==18069== Profiling application: ./daxpy==18069== Profiling result:
Type Time(%) Time Calls Avg Min Max NameGPU activities: 65.57% 2.7894ms 2 1.3947ms 1.3917ms 1.3977ms [CUDA memcpy HtoD]
33.36% 1.4192ms 1 1.4192ms 1.4192ms 1.4192ms [CUDA memcpy DtoH]1.07% 45.632us 1 45.632us 45.632us 45.632us cuda_daxpy(int, double, double*, double*)
API calls: 97.35% 252.07ms 2 126.03ms 485.84us 251.58ms cudaMalloc1.84% 4.7743ms 3 1.5914ms 1.4127ms 1.7897ms cudaMemcpy0.34% 883.73us 188 4.7000us 145ns 196.64us cuDeviceGetAttribute0.23% 593.04us 2 296.52us 233.54us 359.51us cudaFree0.17% 436.19us 2 218.09us 200.67us 235.52us cuDeviceTotalMem0.04% 91.837us 2 45.918us 40.636us 51.201us cuDeviceGetName0.02% 52.945us 1 52.945us 52.945us 52.945us cudaLaunch0.00% 8.2550us 1 8.2550us 8.2550us 8.2550us cudaDeviceSynchronize0.00% 7.7110us 4 1.9270us 131ns 6.3710us cudaSetupArgument0.00% 2.9010us 3 967ns 211ns 2.2530us cuDeviceGetCount0.00% 2.4560us 1 2.4560us 2.4560us 2.4560us cudaConfigureCall0.00% 1.8140us 4 453ns 191ns 740ns cuDeviceGet
プロファイラー(nvprof)で確認する
14
CUDA TOOLKIT DOCUMENTATIONhttp://docs.nvidia.com/cuda/index.html
Programming
Guide
CUDA Runtime
API
HANDS-ON (OPENACC)
2
OPENACC DOCUMENTATIONhttps://www.openacc.org/resources
Best Practice
Guide
Specification
3
DAXPY
//
// daxpy: y[i] = a * x[i] + y[i]
//
void daxpy(int n, double a, double *x, double *y)
{
int i;
for (i = 0; i < n; i++) {
y[i] += a*x[i];
}
}
Y[i] = A * X[i] + Y[i]
4
3つのタスク
Task1: 配列をUnified Memoryで確保する
Task2: GPUカーネルを実行できるようにする
Task3: CPUとGPU間で明示的にデータを確保・移動する
5
ディレクトリ構成、進め方
reference … リファレンスCPUコード
task1 … タスク1
task1-solution … タスク1の答え
task2 … タスク2
task2-solution … タスク2の答え
task3 … タスク3
task3-solution … タスク3の答え
タスクの進め方
• ソース・ファイル (daxpy.c)、Makefile を修正して、正しく動作するようにする
6
TASK0
$ newgrp tgz-gpu-training-2017
$ cd reference
$ module load cuda
$ module load pgi
$ make
$ qsub –g tgz-training -ar 4170 ./batch.sh
Your job **** ("batch.sh") has been submitted
$ qstat
$ ls batch.sh.*
batch.sh.e**** batch.sh.o****
ビルド & ジョブ投入
#!/bin/sh
#$ -cwd
#$ -l q_node=1
#$ -l h_rt=0:10:00
. /etc/profile.d/modules.sh
module load cuda
module load pgi
./daxpy
batch.sh
7
TASK1
Unified Memoryでメモリを確保する
• コンパイル時のオプションで -acc -Minfo=acc –ta=tesla:managed を指定
• -acc OpenACC有効化
• -Minfo コンパイル時のフィードバックを表示
• acc OpenACCに関連するフィードバックを指定
• -ta アクセラレータの種類を指定
• tesla NVIDIA GPU
• managed Unified Memory有効化
配列をUnified Memoryで確保する
8
TASK2GPUカーネルを実行できるようにする
#pragma acc parallel loopfor(int i = 0; j < N; i++)< Your code >
daxpy:23, Generating Tesla code
24, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */23, Generating implicit copy(y[:n])
Generating implicit copyin(x[:n])
ループを並列化
コンパイラフィードバック
9
$ nvprof ./daxpy==37205== NVPROF is profiling process 37205, command: ./daxpyOK==37205== Profiling application: ./daxpy==37205== Profiling result:
Type Time(%) Time Calls Avg Min Max NameGPU activities: 100.00% 4.5814ms 1 4.5814ms 4.5814ms 4.5814ms daxpy_23_gpu
API calls: 78.25% 399.15ms 1 399.15ms 399.15ms 399.15ms cuDevicePrimaryCtxRetain16.49% 84.129ms 1 84.129ms 84.129ms 84.129ms cuDevicePrimaryCtxRelease3.96% 20.224ms 1 20.224ms 20.224ms 20.224ms cuMemAllocManaged0.90% 4.5860ms 1 4.5860ms 4.5860ms 4.5860ms cuStreamSynchronize0.21% 1.0558ms 1 1.0558ms 1.0558ms 1.0558ms cuMemAllocHost0.10% 513.17us 2 256.59us 252.36us 260.81us cuDeviceTotalMem0.05% 264.50us 1 264.50us 264.50us 264.50us cuMemAlloc0.02% 102.74us 1 102.74us 102.74us 102.74us cuModuleLoadData0.01% 34.574us 1 34.574us 34.574us 34.574us cuLaunchKerneltion
…<省略>…
==37205== Unified Memory profiling result:Device "Tesla P100-SXM2-16GB (0)"
Count Avg Size Min Size Max Size Total Size Total Time Name469 35.480KB 4.0000KB 0.9961MB 16.25000MB 1.902387ms Host To Device116 143.45KB 4.0000KB 0.9961MB 16.25000MB 1.402384ms Device To Host41 - - - - 4.495183ms Gpu page fault groups
Total CPU Page faults: 116
GPUは使われている?プロファイラー(nvprof)で確認する
10
TASK3CPUとGPU間で明示的にデータを確保・移動する
daxpy:23, Generating present(y[:],x[:])
Generating Tesla code24, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
main:56, Generating copy(y[:1048576])
Generating copyin(x[:1048576])
CPUとGPU間で明示的にデータを移動
#pragma acc data clauses{< Sequential and/or Parallel code >
}
• copy CPU -> GPU and GPU -> CPU• copyin CPU -> GPU• copyout GPU -> CPU• create GPU上にメモリを確保
clauses
コンパイラフィードバック
11
$ nvprof ./daxpy==37548== NVPROF is profiling process 37548, command: ./daxpyOK==37548== Profiling application: ./daxpy==37548== Profiling result:
Type Time(%) Time Calls Avg Min Max NameGPU activities: 66.42% 1.3504ms 2 675.22us 674.50us 675.94us [CUDA memcpy HtoD]
31.32% 636.71us 1 636.71us 636.71us 636.71us [CUDA memcpy DtoH]2.26% 45.984us 1 45.984us 45.984us 45.984us daxpy_23_gpu
API calls: 76.16% 377.84ms 1 377.84ms 377.84ms 377.84ms cuDevicePrimaryCtxRetain16.59% 82.327ms 1 82.327ms 82.327ms 82.327ms cuDevicePrimaryCtxRelease4.96% 24.591ms 1 24.591ms 24.591ms 24.591ms cuMemHostAlloc1.50% 7.4496ms 1 7.4496ms 7.4496ms 7.4496ms cuMemFreeHost0.27% 1.3540ms 3 451.33us 45.913us 678.56us cuStreamSynchronize0.25% 1.2336ms 3 411.21us 255.51us 714.16us cuMemAlloc0.21% 1.0461ms 1 1.0461ms 1.0461ms 1.0461ms cuMemAllocHost0.02% 97.733us 1 97.733us 97.733us 97.733us cuModuleLoadData0.01% 48.488us 2 24.244us 16.342us 32.146us cuMemcpyHtoDAsync0.01% 35.348us 1 35.348us 35.348us 35.348us cuLaunchKernel0.00% 22.851us 1 22.851us 22.851us 22.851us cuStreamCreate0.00% 9.9860us 1 9.9860us 9.9860us 9.9860us cuMemcpyDtoHAsync0.00% 7.8390us 6 1.3060us 141ns 5.0180us cuCtxSetCurrent0.00% 7.7930us 4 1.9480us 1.0900us 2.8760us cuDeviceGetPCIBusId0.00% 5.4030us 2 2.7010us 1.9360us 3.4670us cuPointerGetAttributes
…<省略>…
データはどう転送される?プロファイラー(nvprof)で確認する
12
OPENACC DOCUMENTATIONhttps://www.openacc.org/resources
Best Practice
Guide
Specification