2013-08-27 4 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; 
} 

приведенные выше результаты не дали правильного ответа. Это что-то не так с личностью? Можно ли лучше использовать силу и другую функцию на комплексном числе?

+1

cuComplex.h выполняет только несколько сложных операций, которые необходимы CUBLAS и CUFFT. Рассмотрите возможность подачи запроса функции для более полной поддержки операций над сложными данными в CUDA. Вы можете сделать это через форму сообщения об ошибке, связанную с зарегистрированным веб-сайтом разработчика. – njuffa

+0

@njuffa У меня была такая же проблема и были размещены вопросы на форуме [NVIDIA Forum] (https://devtalk.nvidia.com/default/topic/549254/complex-arithmetics-in-cuda/) и [StackOverflow] (http: //stackoverflow.com/questions/17405715/complex-arithmetics-in-cuda). Следуя вашему предложению на форуме, я также подал запрос об улучшении через форму системы отчетности об ошибках в июле. Один пользователь 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. При проводке такие вопросы, это полезно, если вы даете фактические результаты вы наблюдения вместе с Ожидаемые результаты.

Вот работал пример, основанный на теореме Муавра в:

$ 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

большое спасибо. Можно ли использовать std :: complex вместо cuDoubleComplex в библиотеке CUDA? – user1285419

+0

Возможно, вы должны представить это как новый вопрос о переполнении стека. –