我对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循环之前等待所有线程相乘。
以下是关于sum和仅在GPU上初始化的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:我现在更改了代码以使用不同的块indcies来运行行计算。 上面的内核编译并运行,但v中的数组元素似乎越来越小而不是重新启动......
我仍然有兴趣了解为什么我不能使用双打以及如果我想使用&lt;来定义我的主机数组,我的代码需要如何更改? vector&gt;。
谢谢,
阿尔钦
答案 0 :(得分:1)
您可以在cublas中解决此问题:
使用cublasSetVector或cublasSetMatrix
将数据复制到GPU使用相应的Get
functions复制结果。
cuda samples中提供了一个工作的cublas示例。
根据其他评论: 对于此问题,没有理由将数据分段为1D块。我推荐的是cublas。但是,如果您想查看其他代码示例,请查看vector add example和matrix multiply example。
对于主机上的双下标矩阵,您应该将其展平,以便您可以使用单个(*
)指针和索引来引用数据。无论您使用的是Cublas还是编写自己的代码,都是如此。
编辑:回复问题中的更新。 你发布的乘法代码对我来说看起来不像矩阵向量乘法,除非你的向量重复N次,以便它与矩阵的长度(NxN)相匹配。然后它似乎是正确的。
求和代码看起来不正确,而且,由于它不以任何方式依赖于idx
,所有线程都在做同样的事情。因此没有并行优势,我们通常不会以这种方式编写GPU代码。
你的向量减法代码似乎近似正确,除了你似乎在矩阵的整个长度(NxN)上做一个向量减法时矩阵向量乘法的结果应该只产生一个向量长度N。
如果此代码可以生成与相同数据集的序列代码匹配的结果,我会感到惊讶。您是否检查过它是否为非平凡数据集生成了正确的结果? (不要使用每个数字相同的数据集。)