2013-08-27 16 views
2

我將我的C++代碼移植到CUDA & CUBLAS。我使用stl :: complex進行復雜計算(例如pow,log,exp等),但是我沒有看到在CuComplex庫中定義的相同函數。我不知道如何創建這些功能,但我發現了一些在線代碼如何在CUBLAS中做複數的權力?

#include <iostream> 
#include <cublas_v2.h> 
#include <cuComplex.h> 
using namespace std; 

typedef cuDoubleComplex Complex; 

#define complex(x, y) make_cuDoubleComplex(x, y) 

__host__ __device__ double cabs(const Complex& z) {return cuCabs(z);} 
__host__ __device__ double carg(const Complex& z) {return atan2(cuCreal(z), cuCimag(z));} 
__host__ __device__ Complex polar(const double &magnitude, const double &angle) {return complex(magnitude*cos(angle), magnitude*sin(angle));} 
__host__ __device__ Complex cexp(const Complex& z) {return polar(exp(cuCreal(z)), cuCimag(z));} 
__host__ __device__ Complex czlog(const Complex& z) {return complex(::log(cabs(z)), carg(z));} 
__host__ __device__ Complex cpow(const Complex& z, const int &exponent) {return cexp(cuCmul(czlog(z), complex((double)exponent, 0)));} 

void main(void) 
{ 
    Complex z=complex(0.34, 0.56); 
    cout << cuCreal(cpow(z, 2)) << " " << cuCimag(cpow(z, 2)) << endl; 
} 

以上結果並沒有給出正確的答案。 cpow有什麼問題嗎?複數的功能和其他功能是否更好?

+1

cuComplex.h只提供CUBLAS和CUFFT所需的一些複雜操作。考慮提交功能請求,以獲得更全面的CUDA複雜數據操作支持。您可以通過從註冊的開發者網站鏈接的錯誤報告表單來完成此操作。 – njuffa

+0

@njuffa我有同樣的問題,並在[NVIDIA論壇](https://devtalk.nvidia.com/default/topic/549254/complex-arithmetics-in-cuda/)和[StackOverflow](http: //stackoverflow.com/questions/17405715/complex-arithmetics-in-cuda)。根據您對論壇的建議,我還通過7月份的錯誤報告系統表格提交了增強請求。一位SO用戶將我引導至此[CUDA Complex Library](https://github.com/jtravs/cuda_complex),這可能對其他用戶也有用。我已通知該圖書館存在的錯誤報告系統。 – JackOLantern

+0

[cusp](http://code.google.com/p/cusp-library/wiki/QuickStartGuide)也有[複雜的實現](http://code.google.com/p/cusp-library/source /browse/cusp/complex.h),這可能會對某些用戶感興趣。 –

回答

3

這是不正確的:

__host__ __device__ double carg(const Complex& z) {return atan2(cuCreal(z), cuCimag(z));} 

polar angle of a complex number是由複數的實部分爲虛部的反正切給出。這相當於由atan2

第二個參數劃分因此,你應該使用第一個參數的比:

__host__ __device__ double carg(const Complex& z) {return atan2(cuCimag(z), cuCreal(z));} 

我不知道你的冪函數(cpow)無論是。你有沒有試過DeMoivre's theorem?我不知道計算方式是最好的方法,但是似乎企業的第一順序是要得到正確的答案。

其他注意事項:

  1. 我不認爲這個問題真的有什麼關係CUBLAS
  2. 當張貼這樣的問題,這是有益的,如果你給你與一起觀察實際效果預期成績。

下面是基於DeMoivre定理一個樣例:

$ cat t233.cu 
#include <iostream> 
#include <math.h> 
#include <cuComplex.h> 
#include <complex> 

typedef double  rtype; 
typedef cuDoubleComplex ctype; 
#define rpart(x) (cuCreal(x)) 
#define ipart(x) (cuCimag(x)) 
#define cmplx(x,y) (make_cuDoubleComplex(x,y)) 

__host__ __device__ rtype carg(const ctype& z) {return (rtype)atan2(ipart(z), rpart(z));} // polar angle 
__host__ __device__ rtype cabs(const ctype& z) {return (rtype)cuCabs(z);} 
__host__ __device__ ctype cp2c(const rtype d, const rtype a) {return cmplx(d*cos(a), d*sin(a));} 
__host__ __device__ ctype cpow(const ctype& z, const int &n) {return cmplx((pow(cabs(z), n)*cos(n*carg(z))), (pow(cabs(z), n)*sin(n*carg(z))));} 

int main(){ 

    double r = 0.34; 
    double i = 0.56; 
    int n = 2; 

    std::complex<double> stl_num(r,i); 
    std::complex<double> cn(n,0); 
    ctype cu_num = cmplx(r,i); 

    std::complex<double> stl_ans = std::pow(stl_num, cn); 
    ctype cu_ans = cpow(cu_num, n); 

    std::cout << "STL real: " << std::real(stl_ans) << " STL imag: " << std::imag(stl_ans) << std::endl; 
    std::cout << "CU real: " << rpart(cu_ans) << " CU imag: " << ipart(cu_ans) << std::endl; 
    return 0; 
} 
$ nvcc -arch=sm_20 -O3 -o t233 t233.cu 
$ ./t233 
STL real: -0.198 STL imag: 0.3808 
CU real: -0.198 CU imag: 0.3808 
$ 

我並不是說這是徹底的測試代碼,但它似乎是在正確的軌道上,並給出了測試中的正確答案案件。

+0

非常感謝。是否有可能在CUDA庫中使用std :: complex而不是cuDoubleComplex? – user1285419

+0

你可能應該把它當作一個新的堆棧溢出問題。 –