我对 C++ 编码很陌生,目前正在尝试使用 CUDA 进行一些 GPU 计算。
基本上我有一个矩阵A (N by N),以及几个向量b和x0。b 和 x0 也有 N 个元素。
这是我要实现的一段代码:
for (unsigned i=1;i<=N;i++){
T sum = 0;
for (unsigned j=1;j<=N;j++){
sum += A[j][i]*x0[j];
}
v[i] = b[i] - sum;
}
其中T是一个模板变量(据我所知,可以分配一个双精度)。
是否有可能并行化整个事情,如果可以,我将如何做到这一点?我还可以使用一些关于如何将此类问题的线程分解为块以及如何将 2D 从主机移动到设备并返回的指针......
如果需要任何其他信息,请告诉我。
编辑 1:在研究了 CUBLAS 并没有走多远之后,我决定展平我的矩阵并自己编写代码。我的第一个发现是我的 cuda 内核不喜欢使用双类型变量/数组[有人可以确认吗?]。
将所有内容转换为浮点数后,我编写的 cuda 内核看起来像这样:
__global__ void cudaMatTimesVect(float *p, float *x0, float *v, float *sum, float *toSum, float *b, int N){
int idx = blockIdx.x * blockDim.x + threadIdx.x; // thread index
if (idx < N*N){
toSum[idx] = p[idx] * x0[blockIdx.x];
}
__syncthreads();
if( idx-(blockIdx.x * blockDim.x) == 0){
for(int i=0; i<blockDim.x; i++){
sum[blockIdx.x] += toSum[idx+i];
}
v[blockIdx.x] = b[blockIdx.x] - sum[blockIdx.x];
}
我不确定syncthreads()命令是否会在尝试执行 sum 循环之前等待所有线程相乘。
以下是有关仅在 GPU 上初始化的 sum 和 toSum 数组的 CPU 代码片段:
float *d_sum;
float *d_toSum;
cudaError_t cudaStatus;
...
// allocate toSum memory
cudaStatus = cudaMalloc(&d_toSum, N*N*sizeof(float));
if (cudaStatus != cudaSuccess){
std::cout << "couldnt allocate device memory for d_toSum!" << std::endl;
cudaFree(d_toSum);
}
// allocate sum mem on device
cudaStatus = cudaMalloc(&d_sum, N*sizeof(float));
if (cudaStatus != cudaSuccess){
std::cout << "couldnt allocate device memory for d_sum" << std::endl;
cudaFree(d_sum);
}
...
...
// call the kernel
cudaMatTimesVect<<<N,N>>>(d_p, d_x0, d_v, d_sum, d_toSum, d_b, N);
...
cudaFree(d_toSum);
cudaFree(d_sum);
这是进行求和最有效的方法吗?
编辑 2:我现在更改了代码以使用不同的块索引来运行行计算。上面的内核编译运行了,但是v中的数组元素似乎越来越小而不是重新启动...
如果我想使用<vector>定义我的主机数组,我仍然有兴趣了解为什么我不能使用双精度数以及我的代码需要如何更改。
谢谢,
阿门