59
K orea I nstitute of A tmospheric P rediction S ystems (KIAPS) ( 재 ) 재재재재재재재재재재재재재재 Python 재 재재 재재 재재재 재재 Fortran, C, CUDA-C, OpenCL-C 재재재재 재재재재 재재재

Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Embed Size (px)

Citation preview

Page 1: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Korea Institute of Atmospheric Prediction Systems

(KIAPS)( 재 ) 한국형수치예보모델개발사업단

Python 의 계산 성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

김기환

Page 2: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2

발표자 …

물리학 전공 ( 광학 이론 )

리눅스 클러스터 만들고 싶어 대학원 인턴 시작 전자기파 시뮬레이션을 위해 병렬 프로그래밍 시작 현재 전지구 대기 시뮬레이션 모델 개발에 참여 중

Page 3: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

3

회사 소개

• 독자 수치예보모델 개발• 2011 년 시작 (2019 년 완

료 )

• 약 900 억 예산

Page 4: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

4

수치예보모델 ?

Page 5: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

5

일기예보는 어떻게 만들어지나 ?

관측 예보

NO!

from 홍성유 , ‘ 대기과학에서의 수치모델링’

Page 6: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

6

일기예보는 어떻게 만들어지나 ?

관측자료처리

분석

관측 예보

수치예보

from 홍성유 , ‘ 대기과학에서의 수치모델링’

Page 7: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

7

수치예보의 중요성

농 / 수산물 공급 예측

❐ 기상예보의 정확도를 결정

국방 / 안보 / 항공 분야

활용도 증가

에너지 공급 / 소비 예측

기상재해로 인한 인명 및 재산피해

최소화 산업 및

가계분야 경제효과 발생

직접적 경제효과 최고 약 6,000 억원

간접적 경제효과 최고 약 6 조5,000 억원

기상예보 정확도 결정요인 기상예보 정확도 향상으로 인한 이익

기상예보 정확도 결정 요인 중 , 수치예보모델은 가장 많은 비중을 차지 ※ 예보관은 수치예보모델의 분석치를 참고 , 관측자료의 질 향상에 수치예보모델 사용 ➠ 실제 수치예보모델의 비중은 50% 이상 ➠ 수치예보모델의 성능이 향상될수록 기상예보 정확도 향상

에너지 공급 / 소비 예측

기상재해로 인한 인명 및 재산 피해 최소화

기상예보 정확도 향상으로 인한 사회 전반적인 이익과 막대한 경제효과

KDI

Page 8: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

8

수치예보의 역사

from 홍성유 , ‘ 대기과학에서의 수치모델링’

1904 : Norwegian V. Bjerknes (1862-1951) :날씨 예측 방법의 수학적 표현 기상 예보 위한 방정식 개발 1922 : British L. F. Richardson (1881-1953) : 수치 예측 모형 개념 정립 및 최초 계산 시도 ( 실패 )

1. 원시방정식 사용2. 계산불안정3. 초기 조건의 문제점

1939 : Swedish C.-G. Rossby : 비발산 와도 방정식 개발 큰 규모 행성파 예측 1948, 1949, J. G. Charney (1917-1981)

Scale analysis 를 통하여 작은 규모 운동 제거 지균풍 가정 : 정역학방정식과 지균풍방정식 이용 소규모 파동 제거 , 일기의 변화에 중요한 영향 미치는 큰 규모 파동만 남김( 순압 준지균 잠재와도 방정식 )

1950 : Princeton Group (Charney, Fjortoft, Von Newman)

ENIAC (Electrical Numerical Integrator and Computer) 첫 수치예보에 성공 !

Page 9: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

9

수치예보모델의 구성 요소

Page 10: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

10

수치예보모델 - 역학코어

from 홍성유 , ‘ 대기과학에서의 수치모델링’

❐ 대기현상의 지배방정식V. Bjerknes (1904) pointed out for the first time that there is a complete set of 7 equations with 7 unknowns that governs the evolution of the atmosphere:

2d pdt

v F v- 운동량 보존

.( )t

v

이상기체 상태방정식

질량 보존 ( 연속방정식 )

1p

ds d QCdt dt T

dq E Cdt

수증기 보존

열역학 제 1 법칙 ( 에너지 보존 )

p RT

7 equations, 7 unknowns (u, v, w, T, p, s, q) solvable

Page 11: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

11

수치예보모델 - 역학코어 ❐ 격자 구조

위경도 격자- 대부분의 수치모델에서 사용- 직교 좌표계- 극특이점 : 극점에 가까울수록 간격이 작아짐 고해상도 모델에서 계산효율성 낮음

육면체구 격자- 극특이점 문제 해결 ( 높은 계산효율성 )

- 분광요소법에 적합- 비직교 좌표계

Page 12: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

12

수치예보모델 - 역학코어<Example> ( 요소 개수 / 변 /face) ngq = 4 (GQ 점의 개수 / 변 /element)

GQ (Gauss-Quadrature) points

1 26

45

3

Page 13: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

13

수치예보모델 - 역학코어 ❐ 공간미분 분광요소법 (Spectral Element method)

- 계산 공간을 요소 (element) 단위로 나눔 Finite Element Method

- 각 요소에서 다항식 공간 (ex, Legendre) 으로 변환 Spectral Method

- 수치 차수를 자유롭게 선택할 수 있고 , 높은 계산효율성을 가짐

❐ 시간미분 nth Runge-Kutta Method 사용

Page 14: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

14

수치예보모델 - 물리과정

from 홍성유 , ‘ 대기과학에서의 수치모델링’

Dynamics

강수과정

단파복사

기압경도력 , 중력 , 원심력 , 코리올리힘 ..

장파복사난류효과

현열 , 잠열

지면마찰효과식생작용

해수면온도

적운대류

오염물질

온실기체

O3Physics

Page 15: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

15

수치예보모델 - 자료동화

from Takemasa Miyoishi and 기상청 수치자료응용팀

Numerical modelsObservations

Data Assimilation

자료동화- 관측자료와 수치모델과의 동화- 더 정확하고 안정된 모델초기값 생성- 주기적인 모델값 보정

Page 16: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

16

수치예보모델의 불확실성

from 홍성유 , ‘ 대기과학에서의 수치모델링’

time

stochasticdeterministic

Unstable system(No-periodicity)

Stable system(Periodicity)

수치모형을 이용한 대기의 예측성

한계 ?대기현상 복잡성(u,v,T,q, etc)

계산상 오차(dx=dt=finite)

Lorenz ( 혼돈역학 ) 2 주

Page 17: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

17

수치예보모델의 불확실성 – 앙상블 예측

from 홍성유 , ‘ 대기과학에서의 수치모델링’

예보관이 신뢰함 예보관이 신뢰 못함

Page 18: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

18

수치예보모델의 예• GEOS 5 (Goddard Earth Observing System)

• 미국 항공우주국 (NASA) 에서 개발한 전지구 대기 모델

• 7 km 격자 해상도 , 30 분 시간간격

• Visualizations by Greg Shirah on August 10, 2014

동영상

Page 19: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

19

발표 주제가 뭐였더라 ? ㅡㅡ ;

Page 20: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Python 이야기를 시작합니다

Page 21: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Motivation

• 대부분의 수치예보모델은 Fortran 으로만 개발되고 있다

• 모델이 막대한 계산성능 ( 그리고 전력소모 ) 을 요구함에도 불구하고 , 새로운 저전력 고성능 머신들(eg. GPU, MIC, FPGA) 을 활용하기가 매우 힘들다– 25km 해상도 , 15 초 간격 , 10 일 예보 6 시간 @5400

cores

• 모델 전체 코드 중 계산이 집중된 부분은 상대적으로 비중이 낮다

• Python 이 대안이 될 수 있지 않을까 ?

Page 22: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Goal

• 전체 모델 코드는 Python 으로 작성– 입출력 , 전처리 , 후처리 , 가시화 , 유닛테스트 , 유지보수

유리

• 계산이 집중된 부분 (hotspot) 만 컴파일 언어로 대체– CPU : Fortran, C– GPU : CUDA-C, OpenCL-C– MIC, FPGA : OpenCL-C

• Python 의 장점과 컴파일 언어들의 장점 모두 활용

Page 23: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

간결하고 가독성 높은 문법 (≈ pseudo code)

쉬운 디버깅 정신건강에 이로움 활용도가 높은 표준 모듈들 (battery included)

과학 / 공학 계산에 유용한 확장 모듈들(Numpy, Scipy, Matplotlib, H5Py, MPI4Py, …)

컴파일 언어 (C, C++, FORTRAN) 와의 쉬운 결합 간편한 GPU, MIC 활용 (PyCUDA, PyOpenCL)

풍부한 기술문서 (http://docs.python.org)

내가 좋아하는 Python 장점들

Page 24: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

참조 : www.scipy.org/Topical_Software

Science Tools for PythonGeneralNumpyScipy

GPGPU ComputingPyCUDAPyOpenCL

Parallel ComputingPETScPyMPIPyparmpi4py

WrappingC/C++/FortranSWIGCythonctypes

Plotting & VisualizationMatplotlibVisltChacoMayaVi

AIPyemFfnetPymorphMonte

BiologyBrianSloppyCellPySAT

Molecular & Atomic ModelingPyMOLBiskitGPAW

GeosciencesGIS PythonPyClimateClimPyCDAT

Bayesian StatsPyMC

OptimizationOpenOpt

Symbolic MathSymPy

ElectromagneticsPyFemax

AstronomyAstroLibPySolar

Dynamic SystemsSimpyPyDSTool

Finite ElementsSfePyescript

Page 25: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Numpy : 과학 / 공학 계산을 위한 기본 모듈 패키지• 풍부한 기능의 N- 차원 배열• Broadcasting 함수 연산• C, C++, FORTRAN 코드 결합을 위한 도구 (f2py)

• Linear algebra, Fourier transform, Random number

Scipy : 확장 모듈 패키지

Numpy & Scipy

• statistics

• optimization

• numerical integration

• linear algebra

• Fourier transforms

• signal processing

• image processing

• ODE solvers

• special functions

참조 : www.scipy.org

Page 26: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

1-D Poisson equation

Problem

Exact solution

Scipy 예제 - 1D Poisson Eq.

Page 27: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Numeric solution: Central finite-difference method

Matrix form

Scipy 예제 - 1D Poisson Eq.

Page 28: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Scipy 예제 - 1D Poisson Eq.import numpy as npfrom scipy.sparse import spdiagsfrom scipy.sparse.linalg import spsolve

omega = 5.4u0, u1 = 0, 1func = lambda x: omega**2 * np.sin(omega * x)

nx = 100; x = np.linspace(0, 1, nx); dx = x[1] – x[0]u_exact = np.sin(omega*x) – (np.sin(omega) – 1) * x

arr = np.ones(nx-2)A = spdiags([-arr, 2*arr, -arr], [-1, 0, 1], nx-2, nx-2)b = func(x[1:-1]) * dx**2; b[0] += u0; b[-1] += u1

u = np.zeros_like(x)u[0], u[-1], u[1:-1] = u0, u1, spsolve(A.tocsr(), b)print np.linalg.norm(u_exact, u) == 0

$ python 1d_poisson.pyTrue

실행

Page 29: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Scipy 예제 - 1D Poisson Eq. (Plot)import matplotlib.pyplot as plt

plt.plot(x, u_exact, '.-k', label='Exact')plt.plot(x, u_scipy, '.-b', label='Scipy')plt.title('1-D Poisson')plt.xlabel('x'); plt.ylabel(‘u(x)'); plt.legend()plt.show()

Page 30: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2-D wave equation

Numerics : Central finite-difference

Numpy 예제 – 2D Wave Eq.

Page 31: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Numpy 예제 - 2D Wave Eq.#!/usr/bin/env pythonimport numpy as np

# setupnx, ny = 1000, 800tmax, tgap = 600, 100

# allocation c = np.ones((nx, ny)) * 0.25 f = np.zeros_like(c) g = np.zeros_like(c)

# main time loop sl = slice(1, -1)sls = (sl, sl)for tstep in xrange(1, tmax+1): f[sls] = c[sls] * (g[2:,sl] + g[:-2,sl] + g[sl,2:] + g[sl,:-2] - 4*g[sls]) + 2*g[sls] - f[sls] g[sls] = c[sls] * (f[2:,sl] + f[:-2,sl] + f[sl,2:] + f[sl,:-2] - 4*f[sls]) + 2*f[sls] - g[sls] g[nx/2,ny/2] = np.sin(0.4 * tstep)

wave2d.py

Page 32: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Numpy 예제 - 2D Wave Eq.# allocation(…)

# plotimport matplotlib.pyplot as plt imag = plt.imshow(f, vmin=-0.1, vmax=0.1) plt.colorbar()

# main time loop for tstep in xrange(1, tmax+1): (…) if tstep % tgap == 0: print('tstep= %d' % tstep) imag.set_array(f) plt.savefig('./png/%.4d.png' % tstep) #plt.draw()

Plot

$ ./wave2d.pytstep= 100tstep= 200tstep= 300tstep= 400tstep= 500tstep= 600$ display png/*

실행

Page 33: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Numpy 예제 - 2D Wave Eq.Plot

0100.png 0400.png 0600.png

Page 34: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Hotspot 을Fortran 코드로 바꿔봅시다

Page 35: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

f2py• Python 과 Fortran 과의 쉬운 연동 제공• Fortran 의 Subroutine, Function, Module 을 Python 에서

호출• Fortran 에서 Python function 호출 (callback)

• Multi-dimensional Numpy array 인자 가능• Fortran 77/90/95 지원• Signature 파일 (.pyf) 로부터 Python 확장 모듈 생성• NumPy 프로젝트에서 개발

Python + Fortran using f2py

참조 : www.scipy.org

Page 36: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Numpy 예제 - 2D Wave Eq.코어 계산 부분을 function 으로 선언#!/usr/bin/env pythonimport numpy as np

def update_core(f, g, c): sl = slice(1, -1) sls = (sl, sl) f[sls] = c[sls] * (g[2:,sl] + g[:-2,sl] + g[sl,2:] + g[sl,:-2] - 4*g[sls]) + 2*g[sls] - f[sls] (…)

# main time loop for tstep in xrange(1, tmax+1): update_core(f, g, c) update_core(g, f, c) (…)

wave2d_python.py

Page 37: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2D Wave Eq. (Python + Fortran)update_core() 함수를 Fortran subroutine 으로 변경

SUBROUTINE update_core(f, g, c, nx, ny) IMPLICIT NONE INTEGER, INTENT(in) :: nx, ny DOUBLE PRECISION, DIMENSION(nx,ny), INTENT(inout) :: f DOUBLE PRECISION, DIMENSION(nx,ny), INTENT(in) :: g, c

f(:nx-1,2:ny-1) = c(2:nx-1,2:ny-1) * (g(3:,2:ny-1) + g(:nx-2,2:ny-1) & + g(2:nx-1,3:) + g(2:nx-1,:ny-2) - 4*g(2:nx-1,2:ny-1)) & + 2*g(2:nx-1,2:ny-1) - f(2:nx-1,2:ny-1)

END SUBROUTINE update_core

ext_core.f90

컴파일 , ext_core.so 생성$ f2py –c –fcompiler=gnu95 –m ext_f90.so ext_core.f90

Page 38: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2D Wave Eq. (Python + Fortran)계산 코어를 Fortran subroutine 으로 변경

#!/usr/bin/env pythonimport numpy as npfrom ext_f90 import update_core

(…)

# main time loop for tstep in xrange(1, tmax+1): update_core(f, g, c) update_core(g, f, c) (…)

wave2d_fortran.py

Page 39: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Hotspot 을C 코드로 바꿔봅시다

Page 40: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2D Wave Eq. (Python + C)update_core() 함수를 C function 으로 변경#include <Python.h>#include <numpy/arrayobject.h>

static PyObject *update_core_py(PyObject *self, PyObject *args) { int nx, ny; PyArrayObject *F, *G, *C; if (!PyArg_ParseTuple(args, “OOOii”, &F, &G, &C, &nx, &ny)) return NULL;

double *f, *g, *c; int i, j, idx;

f = (double *)(F->data); g = (double *)(G->data); c = (double *)(C->data);

for (i = 0; i < nx; i++) { for (j = 0; j < ny; j++) { idx = i*ny +j; f[idx] = c[idx] * (g[idx-ny] + g[idx+ny] + g[idx-1] + g[idx+1] - 4*g[idx]) + 2*g[idx] - f[idx]; } }

Py_RETURN_NONE;}

ext_core.c

( 계속 )

Python C API 사용

Page 41: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2D Wave Eq. (Python + C)update_core() 함수를 C function 으로 변경static PyMethodDef ufunc_methods[] = { {“update_core”, update_core_py, METH_VARARGS, “”}, {NULL, NULL, 0, NULL}};

PyMODINIT_FUNC initext_c() { Py_InitModule(“ext_c”, ufunc_methods); import_array();}

이어서

컴파일 , ext_core.so 생성$ gcc –O3 –fPIC –g –I/usr/include/python2.7 –c ext_core.c –o ext_c.o$ gcc –shared ext_core.o –o ext_c.so

Page 42: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Hotspot 을CUDA 코드로 바꿔봅시다

Page 43: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

GPU (Graphics Processing Unit)

CPU 는 임의의 메모리 접근 , 흐름 제어를 포함하는 범용 연산에 적합 GPU 는 많은 데이터에 동일한 연산을 수행하는 데이터 병렬 연산에 적합 GPU 의 메모리 대역폭이 CPU 보다 높다 (eg. 180 GB/s vs 40 GB/s)

CPU vs GPU

Page 44: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

데이터 병렬 연산 – ex) 벡터합

모든 데이터에 동일한 연산

Page 45: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

CUDA/OpenCL 의 Python wrapper

모든 객체의 동적 할당 / 자동 해제 자동 에러 체크 : 파이썬 예외처리로 변환 JIT (Just-In-Time) 컴파일 빠른 개발 및 디버깅

PyCUDA/PyOpenCL

mathema.tician.de/software/pycudamathema.tician.de/software/pyopencl

Page 46: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2D Wave Eq. (Python + CUDA)update_core() 함수를 CUDA kernel 로 변경__global__ void update_core(double *f, double *g, double *c, int nx, int ny) { int tid = blockIdx.x * blockDim.x + threadIdx.x; int i = tid / ny; int j = tid % ny;

if (i > 0 && j > 0 && i < nx-1 && j < ny-1) { f[tid] = c[tid] * (g[tid-ny] + g[tid+ny] + g[tid-1] + g[tid+1] - 4*g[tid]) + 2*g[tid] - f[tid]; }}

__global__ void update_src(double *f, double val, int idx0) { int tid = blockIdx.x * blockDim.x + threadIdx.x; if (tid == 0) f[idx0] += val;}

ext_core.cu

Page 47: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2D Wave Eq. (Python + CUDA)

#!/usr/bin/env python import numpy as np import pycuda.driver as cuda import pycuda.autoinit

# setup nx, ny = 1000, 800 tmax, tgap = 600, 100

# allocation c = np.ones((nx, ny)) * 0.25 f = np.zeros_like(c)

c_gpu = cuda.to_device(c)f_gpu = cuda.to_device(f) g_gpu = cuda.to_device(f)

wave2d_cuda.py

( 계속 )

Page 48: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2D Wave Eq. (Python + CUDA)# cuda kernels from pycuda.compiler import SourceModule kernels = open('ext_core.cu').read() mod = SourceModule(kernels) update_core = mod.get_function('update_core') update_src = mod.get_function('update_src')

bs, gs = (256,1,1), (nx*ny/256+1,1) nnx, nny = np.int32(nx), np.int32(ny) src_val = lambda tstep: np.sin(0.4 * tstep) src_idx = np.int32( (nx/2)*ny + ny/2 )

# plot(…)

# main time loop for tstep in xrange(1, tmax+1): update_core(f_gpu, g_gpu, c_gpu, nnx, nny, block=bs, grid=gs) update_core(g_gpu, f_gpu, c_gpu, nnx, nny, block=bs, grid=gs) update_src(g_gpu, src_val(tstep), src_idx, block=bs, grid=(1,1)) (…)

( 이어서 )

Page 49: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Hotspot 을OpenCL 코드로 바꿔봅시다

Page 50: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Intel MIC (Many Integrated Core)

~ 60 pentium cores

Page 51: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2D Wave Eq. (Python + OpenCL)update_core() 함수를 OpenCL kernel 로 변경#pragma OPENCL EXTENSION cl_amd_fp64 : enable

__kernel void update_core(__global double *f, __global double *g, __global double *c, int nx, int ny) { int tid = get_global_id(0); int i = tid / ny; int j = tid % ny;

if (i > 0 && j > 0 && i < nx-1 && j < ny-1) f[tid] = c[tid] * (g[tid-ny] + g[tid+ny] + g[tid-1] + g[tid+1] - 4*g[tid]) + 2*g[tid] - f[tid];}

__kernel void update_src(__global double *f, __global double val, int idx0) { int tid = get_global_id(0); if (tid == 0) f[idx0] += val;}

ext_core.cl

Page 52: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2D Wave Eq. (Python + OpenCL)

#!/usr/bin/env python import numpy as np import pyopencl as cl

platforms = cl.get_platforms()devices = platforms[0].get_devices() # 1st platformcontext = cl.Context(devices)queue = cl.CommandQueue(context, devices[0]) # 1st device

# setup nx, ny = 1000, 800 tmax, tgap = 600, 100

# allocation c = np.ones((nx, ny)) * 0.25 f = np.zeros_like(c)

c_dev = cl.Buffer(context, cl.mem_flags.COPY_HOST_PTR, hostbuf=c)f_dev = cl.Buffer(context, cl.mem_flags.COPY_HOST_PTR, hostbuf=f) g_dev = cl.Buffer(context, cl.mem_flags.COPY_HOST_PTR, hostbuf=f)

wave2d_opencl.py

( 계속 )

Page 53: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

2D Wave Eq. (Python + OpenCL)# opencl kernels kernels = open('ext_core.cl').read() mod = cl.Program(context, kernels).build()update_core = mod.update_coreupdate_src = mod. update_src

bs, gs = (60,), (nx*ny/256+1,) nnx, nny = np.int32(nx), np.int32(ny) src_val = lambda tstep: np.sin(0.4 * tstep) src_idx = np.int32( (nx/2)*ny + ny/2 )

# plot(…)

# main time loop for tstep in xrange(1, tmax+1): update_core(queue, bs, gs, f_dev, g_dev, c_dev, nnx, nny) update_core(queue, bs, gs, g_dev, f_dev, c_dev, nnx, nny) update_src(queue, bs, gs, g_dev, src_val(tstep), src_idx) (…)

( 이어서 )

Page 54: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Python 성능 비교 동일한 조건의 3 차원 전자기 시뮬레이션 (FDTD) 실행 시간 비교

빛의 이중 슬릿 투과 시뮬레이션 (Maxwell 방정식 )

Page 55: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Python 성능 비교 빛의 이중 슬릿 투과 시뮬레이션 결과

Page 56: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Python 성능 비교 (CPU) Python-C API 를 사용하여 계산이 집중된 부분만 C 코드로 작성함

Single CPU thread 최적화 코드 (SSE, OpenMP)

C Python+C C Python+CGFLOPS 0.35 0.35 4.60 4.52

1.7 % 성능 차이

Page 57: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Python 성능 비교 (GPU)

PyCUDA 를 사용하여 계산이 집중된 부분만 CUDA 커널로 작성CUDA-C PyCUDA

GFLOPS 20.16 20.16

거의 차이 없음

Page 58: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Python 에서 C, Fortran, CUDA-C, OpenCL-C 와 쉽게 연동할 수 있다 수치모델 메인은 Python 으로 작성 , 계산이 집중된 부분만 컴파일 언어로 대체한다 .

계산성능이 중요한 대규모의 과학계산 분야에서도 Python은 훌륭한 대안이 될 수 있다

Wrap up

Page 59: Python의 계산성능 향상을 위해 Fortran, C, CUDA-C, OpenCL-C 코드들과 연동하기

Have your fun with Python!

Thank you