CUDA Array-Vector乘法

时间:2016-01-11 22:18:49

标签: c++ arrays 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所以基本上总和i给出正确的值,但C [i]总是返回6,尽管有分配的总和值。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

  1. 每当您遇到CUDA代码时遇到问题,最好使用proper cuda error checking并使用cuda-memcheck运行代码。这只是我做的锅炉声明。在这种情况下,它实际上不会显示您所显示的代码的问题。

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

  3. 为了产生正确的结果,您的内核依赖于合作让多个线程更新单个位置(C[i])。但是,这需要线程之间的一些协调。如果没有任何协调,您将使线程处于竞争状态,并且结果将是不可预测的。我们可以使用a parallel reduction对此进行排序,将每个单独线程的部分产品加在一起,或者为了简单起见,我们可以使用atomicAdd operation来强制线程更新(添加到C[i]一个一个,所以他们不会互相踩踏。因此,使用atomicAdd还可以提供必要的添加(+)操作,这在内核中是不存在的。

  4. 这是一个工作代码,其中涉及第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
    $