2012-04-04 7 views
3

OpenCL에는 복소수에 대한 지원이 없으므로이 기능을 읽었을 때 곧 표시되지는 않을 것입니다. 그러나 몇 가지 예에서는 OpenCL 커널 (예 : FFT 구현)에서 복소수를 사용합니다.OpenCL에서 복소수 지원

아무도이 경험이 있습니까? OpenCL에서 복소수 지원을 가능하게하는 "최상의"방법은 무엇입니까? float2를 사용하여 실수 부와 허수 부를 포함한다고 가정하겠습니다. 그러나 매크로 세트를 작성해야합니까? 아니면 인라인 함수가 더 좋습니까? 이 목적을 위해 함수/매크로 세트가 이미 존재하는지 알 수 있습니까?

+0

여기에 조 그것을하는 방법을 llustrates : http://developer.amd.com/resources/documentation-articles/articles-whitepapers/opencl-optimization-case-study-fast-fourier-transform-part-1/ – ChrisF

답변

6

그래서 OpenCL에서 복잡한 숫자를 처리하는 함수 집합이 필요 했으므로이 집합을 구현했습니다. 특히 나는 합과 빼기 (사소한, 표준 벡터 연산으로 수행 할 수 있음), 곱하기, 나누기, 복소수 모듈러스, 인수 (또는 각도) 및 제곱근 가져 오기가 필요했습니다.
관련 위키 피 디아 기사 :
http://en.wikipedia.org/wiki/Complex_number#Absolute_value_and_argument
http://en.wikipedia.org/wiki/Square_root#Principal_square_root_of_a_complex_number
이 대부분 사소한, 그러나 사람이 시간을 절약 할 수있는 희망 그래서, 시간이 좀 걸릴 않습니다, 여기 간다 :

//2 component vector to hold the real and imaginary parts of a complex number: 
typedef float2 cfloat; 

#define I ((cfloat)(0.0, 1.0)) 


/* 
* Return Real (Imaginary) component of complex number: 
*/ 
inline float real(cfloat a){ 
    return a.x; 
} 
inline float imag(cfloat a){ 
    return a.y; 
} 

/* 
* Get the modulus of a complex number (its length): 
*/ 
inline float cmod(cfloat a){ 
    return (sqrt(a.x*a.x + a.y*a.y)); 
} 

/* 
* Get the argument of a complex number (its angle): 
* http://en.wikipedia.org/wiki/Complex_number#Absolute_value_and_argument 
*/ 
inline float carg(cfloat a){ 
    if(a.x > 0){ 
     return atan(a.y/a.x); 

    }else if(a.x < 0 && a.y >= 0){ 
     return atan(a.y/a.x) + M_PI; 

    }else if(a.x < 0 && a.y < 0){ 
     return atan(a.y/a.x) - M_PI; 

    }else if(a.x == 0 && a.y > 0){ 
     return M_PI/2; 

    }else if(a.x == 0 && a.y < 0){ 
     return -M_PI/2; 

    }else{ 
     return 0; 
    } 
} 

/* 
* Multiply two complex numbers: 
* 
* a = (aReal + I*aImag) 
* b = (bReal + I*bImag) 
* a * b = (aReal + I*aImag) * (bReal + I*bImag) 
*  = aReal*bReal +I*aReal*bImag +I*aImag*bReal +I^2*aImag*bImag 
*  = (aReal*bReal - aImag*bImag) + I*(aReal*bImag + aImag*bReal) 
*/ 
inline cfloat cmult(cfloat a, cfloat b){ 
    return (cfloat)(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x); 
} 


/* 
* Divide two complex numbers: 
* 
* aReal + I*aImag  (aReal + I*aImag) * (bReal - I*bImag) 
* ----------------- = --------------------------------------- 
* bReal + I*bImag  (bReal + I*bImag) * (bReal - I*bImag) 
* 
*  aReal*bReal - I*aReal*bImag + I*aImag*bReal - I^2*aImag*bImag 
*  = --------------------------------------------------------------- 
*   bReal^2 - I*bReal*bImag + I*bImag*bReal -I^2*bImag^2 
* 
*  aReal*bReal + aImag*bImag   aImag*bReal - Real*bImag 
*  = ---------------------------- + I* -------------------------- 
*   bReal^2 + bImag^2    bReal^2 + bImag^2 
* 
*/ 
inline cfloat cdiv(cfloat a, cfloat b){ 
    return (cfloat)((a.x*b.x + a.y*b.y)/(b.x*b.x + b.y*b.y), (a.y*b.x - a.x*b.y)/(b.x*b.x + b.y*b.y)); 
} 


/* 
* Square root of complex number. 
* Although a complex number has two square roots, numerically we will 
* only determine one of them -the principal square root, see wikipedia 
* for more info: 
* http://en.wikipedia.org/wiki/Square_root#Principal_square_root_of_a_complex_number 
*/ 
inline cfloat csqrt(cfloat a){ 
    return (cfloat)(sqrt(cmod(a)) * cos(carg(a)/2), sqrt(cmod(a)) * sin(carg(a)/2)); 
} 
+1

그 한 글자' #define 나는 언젠가 너를 무서워 할 것이다 ;-). – rubenvb

+0

@rubenvb 왜 그런가요? 당신은 모범이 있습니까? –

+1

carg (cfloat a)를 OpenCL에서 이미 구현 된 atan2 함수로 대체 할 수 있습니다. https://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/atan.html – Dirklinux

4

PyOpenCL가있다 OpenCL을 복잡한 숫자의 좀 더 완전하고 강력한 구현 :

https://github.com/pyopencl/pyopencl/blob/master/pyopencl/cl/pyopencl-complex.h

+0

거터 Tip, danke :) 저장소에서 "덧셈 (실수 + 복소수)과 곱하기 (복소수 * 복소수)가 정의되었지만 잘못된 결과가 나오는 것에주의하십시오". 이게 무슨 뜻이야? 실수 + 복소 덧셈은 실제로 정의되지 않았고 복소수 * 복소 곱셈은'return (TP) (a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x)로 확장 될 것이다. }'나에게 잘 보이거나 내가 간과하고있는 것이 있는가? –

+0

링크 업데이트 : https://github.com/pyopencl/pyopencl/blob/master/pyopencl/cl/pyopencl-complex.h – tesch1