2016-01-11 217 views
0

嗨,我正在CUDA技术的第一步,但我认为我不明白。CUDA阵列 - 矢量乘法

我试图通过矢量乘二维数组,但有什么不工作

这里是我试图找出代码:

#include <stdio.h> 
#include <stdlib.h> 

#define N 2 

__global__ void Multiply(int A[N][N], int B[N], int C[N]){ 
      int i = threadIdx.x; 
      int j = threadIdx.y; 

      int sum = A[i][j] * B[j]; 
      C[i]= sum; 
      printf("%d,%d ", sum, C[i]); 
} 

int main(){ 

int A[N][N] ={ {1,1}, 
       {1,1} 
      }; 
int B[N] = {4,6}; 
int C[N] = {0,0};  
int (*aA)[N], (*aB), (*aC); 

cudaMalloc((void**)&aA, (N*N)*sizeof(int)); 
cudaMalloc((void**)&aB, (N)*sizeof(int)); 
cudaMalloc((void**)&aC, (N)*sizeof(int)); 

cudaMemcpy(aA, A, (N*N)*sizeof(int), cudaMemcpyHostToDevice); 
cudaMemcpy(aB, B, (N)*sizeof(int), cudaMemcpyHostToDevice); 
cudaMemcpy(aC, C, (N)*sizeof(int), cudaMemcpyHostToDevice); 

int numBlocks = 1; 
dim3 threadsPerBlock(N,N); 
Multiply<<<numBlocks,threadsPerBlock>>>(aA,aB,aC); 

cudaMemcpy(C, aC, (N)*sizeof(int), cudaMemcpyDeviceToHost); 


cudaFree(aA); 
cudaFree(aB); 
cudaFree(aC); 

printf("\n"); 
system("pause"); 

} 
在这种情况下,输出是

:4, 6 4,6 6,6 6,6所以基本上我给出正确的值的总和,但C [i]总是返回6,尽管有总和值分配给它。

我在做什么错?

回答

1
  1. 您有一个CUDA代码的麻烦任何时候,它的使用proper cuda error checkingcuda-memcheck运行代码是个好主意。这仅仅是我所做的一个锅炉陈述。这实际上并不能解决你在这种情况下显示的代码问题。

  2. 正如在一个现在被删除的答案中已经指出的那样,你实际上并没有把任何东西加在一起。即使你有一个名为sum的变量,它实际上并不是任何东西的总和,并且在内核代码中没有+或求和操作。你不是在编写一个将任何东西加在一起的内核。

  3. 为了产生一个正确的结果,你的内核依赖协作地让多个线程更新一个位置(C[i])。但是,这需要线程之间的一些协调。如果没有任何协调,你将会在相互竞争的情况下产生线索,结果将是不可预测的。我们可以使用a parallel reduction对此进行排序,将每个单独线程的部分产品进行汇总,或者为了简单起见,我们可以使用atomicAddoperation,这将强制线程逐个更新(添加到)C[i],因此它们不要踩在彼此身上。因此,使用atomicAdd还会提供必要的添加(+)操作,这在内核中是缺少的。

这里是一个工作代码,其中第2项和第3项是针对性的。您可以使用cuda-memcheck运行它以验证行为正确性,即使它没有明确的错误检查:

$ cat t1037.cu 
#include <stdio.h> 
#include <stdlib.h> 

#define N 2 

__global__ void Multiply(int A[N][N], int B[N], int C[N]){ 
      int i = threadIdx.x; 
      int j = threadIdx.y; 

      int product = A[i][j] * B[j]; 
      atomicAdd(C+i, product); 
    //   printf("%d,%d ", product, C[i]); 
} 

int main(){ 

int A[N][N] ={ {1,1}, 
       {1,1} 
      }; 
int B[N] = {4,6}; 
int C[N] = {0,0}; 
int (*aA)[N], (*aB), (*aC), i; 

cudaMalloc((void**)&aA, (N*N)*sizeof(int)); 
cudaMalloc((void**)&aB, (N)*sizeof(int)); 
cudaMalloc((void**)&aC, (N)*sizeof(int)); 

cudaMemcpy(aA, A, (N*N)*sizeof(int), cudaMemcpyHostToDevice); 
cudaMemcpy(aB, B, (N)*sizeof(int), cudaMemcpyHostToDevice); 
cudaMemcpy(aC, C, (N)*sizeof(int), cudaMemcpyHostToDevice); 

int numBlocks = 1; 
dim3 threadsPerBlock(N,N); 
Multiply<<<numBlocks,threadsPerBlock>>>(aA,aB,aC); 

cudaMemcpy(C, aC, (N)*sizeof(int), cudaMemcpyDeviceToHost); 

for (i=0; i<N; i++){ 
    printf("C[%d] = %d\n",i,C[i]); 
    } 
cudaFree(aA); 
cudaFree(aB); 
cudaFree(aC); 

printf("\n"); 

} 
$ nvcc -o t1037 t1037.cu 
$ cuda-memcheck ./t1037 
========= CUDA-MEMCHECK 
C[0] = 10 
C[1] = 10 

========= ERROR SUMMARY: 0 errors 
$