【发布时间】:2013-07-04 19:20:26
【问题描述】:
我正在尝试通过编写基本代码来学习 CUDA,这有望使我能够更好地将现有的 C++ 代码转换为 CUDA(用于研究)。
我需要做一些复数操作,所以我编写了这个非常基本的代码来将复数数组与实数相乘 在 GPU 内核中。
#include <complex>
#include <iostream>
#include <cmath>
#include "cuda.h"
#include "math.h"
#include "cuComplex.h"
#define n 5
using namespace std;
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
{
if (code != cudaSuccess)
{
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) exit(code);
}
}
__global__ void func( double *s, cuDoubleComplex *j, cuDoubleComplex *calc ) {
int tid = blockIdx.x;
calc[tid] = cuCmul(j[tid], make_cuDoubleComplex(*s, 0));
}
int main( void ) {
cuDoubleComplex calc[n+1], *dev_j, *dev_calc;
double *dev_s, s[n+1] = { 2.0, 2.0, 2.0, 2.0, 2.0 };
//complex<double> j[n+1]
cuDoubleComplex j[n+1];
for (int i = 1; i <= n; i++) {
j[i] = make_cuDoubleComplex(0, 5);
cout << "\nJ cout = " << cuCreal(j[i]) << ", " << cuCimag(j[i]);
}
// allocate the memory on the GPU
cudaMalloc( (void**)&dev_s, (n+1) * sizeof(double) );
cudaMalloc( (void**)&dev_j, (n+1) * sizeof(double) );
cudaMalloc( (void**)&dev_calc, (n+1) * sizeof(double) );
cudaMemcpy( dev_s, s, (n+1) * sizeof(double), cudaMemcpyHostToDevice );
cudaMemcpy( dev_j, j, (n+1) * sizeof(double), cudaMemcpyHostToDevice );
func<<<n,1>>>( dev_s, dev_j, dev_calc );
//kernel<<<1,1>>>(a_d);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaMemcpy(calc, dev_calc, (n+1) * sizeof(double), cudaMemcpyDeviceToHost) );
//cudaMemcpy( calc, dev_calc, (n+1) * sizeof(double), cudaMemcpyDeviceToHost );
for (int i = 1; i <= n; i++) {
cout << "\nCALC cout = " << cuCreal(calc[i]) << ", " << cuCimag(calc[i]);
}
return 0;
}
最后的答案是错误的,我还发现了其他一些我没有得到预期值的地方。
1) 在以下代码行之后,我期望 'j' 的所有元素都有一个复杂的双精度数组 (0, 5i)。但是,我得到的都是 0。这是为什么呢?
j[i] = make_cuDoubleComplex(0, 5);
2) 为什么我不能使用 cout 打印我的数组?下面显示的代码行给出了以下错误:没有运算符“
cout << "\nJ = " << j[i];
3) GPU 函数 'func' 应该给出一个 (0, 10i) 数组作为最终答案,它给出了如下随机值:
CALC = -1.#QNAN0
CALC = -1.#QNAN0
CALC = -9255963134931783100000000...000.. etc
CALC = -9255963134931783100000000...000.. etc
4) 对于我的实际研究,复数数组“j”将以 complex(double) 的格式给出,而不是 cuDoubleComplex。我可以使用函数'func'对'j'复杂(双)数组进行类似的操作吗?如果没有,我有什么选择?
我认为我已经很好地解释了自己,但请随时提出任何后续问题。 对 C++ 和 CUDA 不熟悉,所以很好:D
【问题讨论】:
-
当您尝试将 单个复数乘以 GPU 内核中的实数时发生了什么?