카테고리 없음
R에서 OpenCL 테스트 - ATI 그래픽 카드 이용
관리자..
2012. 9. 11. 22:21
OpenCL 패키지 예제 코드로 테스트 해 봤다. 내 GPU가 배정밀도 실수 연산 원을 안해서 단정밀도 실수연산 예제만 해 봄.
원래 코드는 여기서
http://www.rforge.net/doc/packages/OpenCL/html/oclRun.html
가독성 위해 약간 고쳤다. C함수 이름이 원래 dnrom 이었는데 R 함수 dnorm 이랑 헷갈리니까 openCLDNorm 으로 바꾼 정도.
## 몹시 귀찮은 부분인데, C로 직접 코드를 짜야 한다 이 경우는. 이 라이브러리가 전부 다 그런지 싶고, 나도 상식적으로 생각해도 C 말고 다른 코드를 GPU에 보내는 건 좀 웃긴 것 같고.. 근데 이러면 쓰기 귀찮아짐 아무래도.. 여튼 아래 코드 스트링은 정규분포밀도 함수 코드로 R에 표준으로 들어있는 dnorm 함수에 대응된다.
# 계산시간 뽑아 본 건데,
원래 코드는 여기서
http://www.rforge.net/doc/packages/OpenCL/html/oclRun.html
가독성 위해 약간 고쳤다. C함수 이름이 원래 dnrom 이었는데 R 함수 dnorm 이랑 헷갈리니까 openCLDNorm 으로 바꾼 정도.
---------
## OpenCL
## OpenCL
library(OpenCL) # 패키지 설치미리 할 것
p = oclPlatforms()
d = oclDevices(p[[1]]) # 내 GPU 환경 보여줌
## 몹시 귀찮은 부분인데, C로 직접 코드를 짜야 한다 이 경우는. 이 라이브러리가 전부 다 그런지 싶고, 나도 상식적으로 생각해도 C 말고 다른 코드를 GPU에 보내는 건 좀 웃긴 것 같고.. 근데 이러면 쓰기 귀찮아짐 아무래도.. 여튼 아래 코드 스트링은 정규분포밀도 함수 코드로 R에 표준으로 들어있는 dnorm 함수에 대응된다.
code = c("
__kernel void openCLDNorm(
__global float* output,
const unsigned int count,
__global float* input,
const float mu, const float sigma)
{
int i = get_global_id(0);
if(i < count)
output[i] = exp(-0.5f * ((input[i] - mu) / sigma) * ((input[i] - mu) / sigma))
/ (sigma * sqrt( 2 * 3.14159265358979323846264338327950288 ) );
};")
## 실제로 OpenCL에 얹는 부분. 코드 짜서, 아래처럼 커널 오브젝트 만들고, 이걸 다시 R 함수로 싸는 3단계 작업이다.
## 실제로 OpenCL에 얹는 부분. 코드 짜서, 아래처럼 커널 오브젝트 만들고, 이걸 다시 R 함수로 싸는 3단계 작업이다.
k.dnorm <- oclSimpleKernel(d[[1]], "openCLDNorm", code, "single")
OpenCLDnorm <- function(x, mu=0, sigma=1, ...) {
oclRun(k.dnorm, length(x), x, mu, sigma, ...)
}
## expect differences since the above uses single-precision but
## it should be close enough
## R 함수 돌린 것과 값은 매우 비슷하다. 언급됐듯 정밀도 문제로 정확히 같게는 안나온다. 이 부분이 사실 수치계산 프로그램들 대단한 건데, 어떤 식으로 하는 건진 몰라도 타입만 잘 맞춰주면 해석적 답과 같은 수치를 보여주는 능력이 있다 (안 그런 경우도 있다) 여튼 다음에 다시 그 얘기는..
OpenCLDnorm(1:10/2) - dnorm(1:10/2)
## R 함수 돌린 것과 값은 매우 비슷하다. 언급됐듯 정밀도 문제로 정확히 같게는 안나온다. 이 부분이 사실 수치계산 프로그램들 대단한 건데, 어떤 식으로 하는 건진 몰라도 타입만 잘 맞춰주면 해석적 답과 같은 수치를 보여주는 능력이 있다 (안 그런 경우도 있다) 여튼 다음에 다시 그 얘기는..
OpenCLDnorm(1:10/2) - dnorm(1:10/2)
# 거의 같은, 관용도 안에 떨어지는 값 보여줌.
system.time(
for (i in 1E1000) {f(1:1E7)}
)
system.time(
for (i in 1E1000) {dnorm(1:1E7)}
)
# 계산시간 뽑아 본 건데,
> system.time(
+ for (i in 1E1000) {f(1:1E7)}
+ )
user system elapsed
0.043 0.050 0.234
>
>
> system.time(
+ for (i in 1E1000) {dnorm(1:1E7)}
+ )
user system elapsed
0.922 0.013 0.935
내 컴퓨터에선 확실히 차이를 보여줬다. 사실 이 부분을 좀 자세히 들여다 봐야 정확하게 뭐라 할 수 있는데, 일단 원칙적으로 GPU를 쓰는 연산이니까 돌아가는 동안 CPU 점유율이 올라가면 안되고, 메모리도 가능하면 GDDR을 써 주는 것이 맞을텐데.. 그게 또 부족하면 어떻게 되는지 봐야 하고 (메인 메모리 쓰는지 스왑하는지 에러내는지 등). 여튼 코드 자체가 범용성이 떨어져서 아직 쓰기엔 불편하지만, 돌아가는 것 확인, R 기본 함수보다 빠른 것 확인. 그리고 제일 중요한 건, ATI 그래픽 카드로 했다는 것. NViDIA면 고생할 필요 없이 참고자료도 많은 CUDA 쓰면 된다.
일단 여기까지..
내 컴퓨터에선 확실히 차이를 보여줬다. 사실 이 부분을 좀 자세히 들여다 봐야 정확하게 뭐라 할 수 있는데, 일단 원칙적으로 GPU를 쓰는 연산이니까 돌아가는 동안 CPU 점유율이 올라가면 안되고, 메모리도 가능하면 GDDR을 써 주는 것이 맞을텐데.. 그게 또 부족하면 어떻게 되는지 봐야 하고 (메인 메모리 쓰는지 스왑하는지 에러내는지 등). 여튼 코드 자체가 범용성이 떨어져서 아직 쓰기엔 불편하지만, 돌아가는 것 확인, R 기본 함수보다 빠른 것 확인. 그리고 제일 중요한 건, ATI 그래픽 카드로 했다는 것. NViDIA면 고생할 필요 없이 참고자료도 많은 CUDA 쓰면 된다.
일단 여기까지..