카테고리 없음

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 으로 바꾼 정도. 


---------
## 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단계 작업이다. 
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) 
# 거의 같은, 관용도 안에 떨어지는 값 보여줌. 

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 쓰면 된다. 

일단 여기까지..