我知道OpenCL不支持複數,而且我讀過的這個功能不會很快顯示出來。 仍然有幾個例子在OpenCL內核中使用複數(例如FFT實現)。OpenCL中的複雜數字支持
有沒有人有這方面的經驗?在OpenCL中啓用複雜數字支持的「最佳」方法是什麼?我假設使用float2來包含實部和虛部,但是我應該寫一組宏還是內聯函數更好?有沒有人知道一組函數/宏是否已經存在用於此目的?
我知道OpenCL不支持複數,而且我讀過的這個功能不會很快顯示出來。 仍然有幾個例子在OpenCL內核中使用複數(例如FFT實現)。OpenCL中的複雜數字支持
有沒有人有這方面的經驗?在OpenCL中啓用複雜數字支持的「最佳」方法是什麼?我假設使用float2來包含實部和虛部,但是我應該寫一組宏還是內聯函數更好?有沒有人知道一組函數/宏是否已經存在用於此目的?
所以,因爲我需要一組函數來處理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));
}
PyOpenCL有在OpenCL中複雜數字的更完整和強大的實現:
https://github.com/pyopencl/pyopencl/blob/master/pyopencl/cl/pyopencl-complex.h
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
鏈接更新:https://github.com/pyopencl/pyopencl/blob/master/pyopencl/cl/pyopencl-complex.h – tesch1 2015-03-18 16:59:24
這篇文章我說明如何做到這一點: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