More Related Content More from NVIDIA Japan (20) 1074: OpenACC プログラミング入門4. OpenACC
シンプル | 強力 | 柔軟
イリノイ大学
MRI画像再構成
70倍 高速化
理研
NICAM- 大気現象シミュレーション
5% のコード変更で
7~8倍 高速化
main()
{
<serial code>
#pragma acc kernels
//自動的にGPUで実行
{
<parallel code>
}
}
OpenACC利用者
8000人+
5. OpenACC ディレクティブ
Program myscience
... serial code ...
!$acc kernels
do k = 1,n1
do i = 1,n2
... parallel code ...
enddo
enddo
!$acc end kernels
...
End Program myscience
CPU GPU
Fortran または C言語の
オリジナルコード
コンパイラへシンプルなヒント
コンパイラがコードを並列化
並列部はGPUで
逐次処理はCPUで動作
コンパイラへの
OpenACC
ヒント
6. OpenMP と OpenACC の比較
main() {
double pi = 0.0; long i;
#pragma omp parallel for reduction(+:pi)
for (i=0; i<N; i++)
{
double t = (double)((i+0.05)/N);
pi += 4.0/(1.0+t*t);
}
printf(“pi = %f¥n”, pi/N);
}
CPU
OpenMP
main() {
double pi = 0.0; long i;
#pragma acc kernels
for (i=0; i<N; i++)
{
double t = (double)((i+0.05)/N);
pi += 4.0/(1.0+t*t);
}
printf(“pi = %f¥n”, pi/N);
}
CPU GPU
OpenACC
CPUコアに
計算処理を分散
GPUコアに
計算処理を分散
8. OpenACC ツールキット
PGIコンパイラ
Free OpenACC compiler for academia
NVProfプロファイラ
Easily find where to add compiler directives
サンプルコード
Learn from examples of real-world algorithms
ドキュメント
Quick start guide, Best practices, Forums
http://developer.nvidia.com/openacc
GPUウィザード
Identify which GPU libraries can jumpstart code
11. 例: SAXPY (Y=A*X+Y)
void saxpy(int n,
float a,
float *x,
float *restrict y)
{
#pragma acc parallel
for (int i = 0; i < n; ++i)
y[i] += a*x[i];
}
...
saxpy(N, 3.0, 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);
...
12. OpenACC 構文: parallel 指示行
• parallel : 並列に実行される領域を指示行で指定
#pragma acc parallel
for(int i=0;i<n;i++){
a[i] = 0.0;
b[i] = 1.0;
c[i] = 2.0;
}
kernel 1 Kernel(カーネル):
GPU上で実行される
関数
13. OpenACC 構文: kernels 指示行
• kernels : 複数のカーネルを作成
#pragma acc kernels
for(int i=0;i<n;i++){
a[i] = 0.0;
b[i] = 1.0;
c[i] = 2.0;
}
#pragma acc kernels
for(int i=0;i<n;i++){
a[i] = b[i] + c[i];
}
kernel 1
kernel 2
Kernel(カーネル):
GPU上で実行される
関数
14. 簡単にコンパイル
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 –ta=nvidia –Minfo=accel saxpy.c
saxpy:
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 */
15. 例:ヤコビ反復法(アルゴリズム)
while ( error > tol ) {
error = 0.0;
for (int j = 1; j < N-1; j++) {
for (int i = 1; i < M-1; i++) {
Anew[j][i] = (A[j][i+1] + A[j][i-1] +
A[j-1][i] + A[j+1][i]) * 0.25;
error = max(error, abs(Anew[j][i] - A[j][i]));
}
}
for (int j = 1; j < N-1; j++) {
for (int i = 1; i < M-1; i++) {
A[j][i] = Anew[j][i];
}
}
}
A(i,j) A(i+1,j)A(i-1,j)
A(i,j-1)
A(i,j+1)
16. 並列領域 (OpenACC)
Parallels と Kernels
— 並列領域を指示
Parallels
— 並列実行スタート
Kernels
— 複数のカーネル
while ( error > tol ) {
error = 0.0;
#pragma acc kernels
for (int j = 1; j < N-1; j++) {
for (int i = 1; i < M-1; i++) {
Anew[j][i] = (A[j][i+1] + A[j][i-1] +
A[j-1][i] + A[j+1][i]) * 0.25;
error = max(error, abs(Anew[j][i] - A[j][i]);
}
}
#pragma acc kernels
for (int j = 1; j < N-1; j++) {
for (int i = 1; i < M-1; i++) {
A[j][i] = Anew[j][i];
}
}
}
17. 簡単に解析(nvprof)
OpenMP / OpenACC
void saxpy(int n, float a,
float *x,
float *restrict y)
{
#pragma acc kernels 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 -Minfo -acc saxpy.c
saxpy:
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
19. 過剰なメモリ転送
while ( error > tol ) {
error = 0.0;
#pragma acc kernels
for (int j = 1; j < N-1; j++) {
for (int i = 1; i < M-1; i++) {
Anew[j][i] = (A[j][i+1] + A[j][i-1] +
A[j-1][i] + A[j+1][i]) * 0.25;
error = max(error, abs(Anew[j][i] - A[j][i]);
}
}
#pragma acc kernels
for (int j = 1; j < N-1; j++) {
for (int i = 1; i < M-1; i++) {
A[j][i] = Anew[j][i];
}
}
}
配列Aへメモリ転送
(CPU->GPU)
配列Anewへメモリ転送
(CPU->GPU)
配列Anewへメモリ転送
(GPU->CPU)
配列Aへメモリ転送
(GPU->CPU)
21. 性能比較
Time(sec) Speedup
CPU1 OpenMP thread 26.186 --
OpenACC(最適化前) 13.638 1.92x
OpenACC(最適化後) 0.773 33.88x
Ubuntu 14.04LTS 64bit
CPU:Intel Xeon CPU E5-1603 v3@2.8GHz x 4
GPU:Tesla K40c