2012-04-04 67 views
3

我知道OpenCL不支持複數,而且我讀過的這個功能不會很快顯示出來。 仍然有幾個例子在OpenCL內核中使用複數(例如FFT實現)。OpenCL中的複雜數字支持

有沒有人有這方面的經驗?在OpenCL中啓用複雜數字支持的「最佳」方法是什麼?我假設使用float2來包含實部和虛部,但是我應該寫一組宏還是內聯函數更好?有沒有人知道一組函數/宏是否已經存在用於此目的?

+0

這篇文章我說明如何做到這一點:http://developer.amd.com/resources/documentation-articles/articles-whitepapers/opencl-optimization-case-study-fast-fourier-transform-part-1/ – ChrisF 2014-10-01 16:15:13

回答

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

那個單字母' #定義我''有一天會咬你;-)。 – rubenvb 2014-06-26 08:54:54

+0

@rubenvb這是爲什麼?你有一個例子嗎? – 2014-07-21 12:50:39

+1

您可以將carg(cfloat a)替換爲已經在OpenCL中實現的atan2函數:https://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/atan.html – Dirklinux 2015-10-20 08:57:15

4

PyOpenCL有在OpenCL中複雜數字的更完整和強大的實現:

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

+0

Guter提示,danke :)從您的存儲庫中「注意添加(實數+複數)和乘法(複數*複數)被定義,但產生錯誤的結果」。這是什麼意思?實際+複數加法實際上沒有定義,而複數乘法將擴展到'return(TP)(a.x * b.x - a.y * b.y,a.x * b.y + a.y * b.x); }'這對我來說看起來很好,還是有我忽略的東西? – 2012-04-19 14:07:17

+0

鏈接更新:https://github.com/pyopencl/pyopencl/blob/master/pyopencl/cl/pyopencl-complex.h – tesch1 2015-03-18 16:59:24