如何在CUBLAS中做复数的力量?

时间:2013-08-27 01:12:27

标签: cuda cublas

我将我的c ++代码移植到CUDA& CUBLAS。我使用stl :: complex进行复杂计算(即pow,log,exp等),但我没有看到CuComplex库中定义的相同函数。我不知道如何创建这些功能,但我在网上找到了一些代码

#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 个答案:

答案 0 :(得分: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. 有任何关系
  3. 在发布此类问题时,如果您提供您正在观察的实际结果以及预期结果,这会有所帮助。
  4. 这是一个基于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
    $
    

    我并不是说这是经过彻底测试的代码,但似乎是在正确的轨道上并为您的测试用例提供了正确的答案。