CUDA内核自动调用内核来完成向量加法.为什么?

CUDA kernel automatically recall kernel to finish vector addition. Why?

本文关键字:内核 向量 为什么 调用 CUDA      更新时间:2023-10-16

我刚开始玩CUDA,所以我尝试了一个教科书式的矢量加法代码。然而,当我指定内核调用只添加向量的前半部分时,后半部分也会被添加!当我包含一些推力库头时,这种行为就会停止。

我完全糊涂了。请参阅下面的代码:

#include <iostream>
using namespace std;
__global__ void VecAdd(float *d_dataA, float *d_dataB, float *d_resultC)
{
    //printf("gridDim.x is %d n",gridDim.x);
    int tid = blockIdx.x * blockDim.x + threadIdx.x;    
//  printf("tid is %d n",tid);
    d_resultC[tid] = d_dataA[tid] + d_dataB[tid];
}
int main() 
{
    const int ARRAY_SIZE = 8*1024;
    const int ARRAY_BYTES = ARRAY_SIZE * sizeof(float);
    float *h_dataA, *h_dataB, *h_resultC;
    float *d_dataA, *d_dataB, *d_resultC;
    h_dataA     = (float *)malloc(ARRAY_BYTES);
    h_dataB     = (float *)malloc(ARRAY_BYTES);
    h_resultC   = (float *)malloc(ARRAY_BYTES);
    for(int i=0; i<ARRAY_SIZE;i++){
        h_dataA[i]=i+1;
        h_dataB[i]=2*(i+1);
    };
    cudaMalloc((void **)&d_dataA,ARRAY_BYTES);
    cudaMalloc((void **)&d_dataB,ARRAY_BYTES);
    cudaMalloc((void **)&d_resultC,ARRAY_BYTES);
    cudaMemcpy(d_dataA, h_dataA,ARRAY_BYTES, cudaMemcpyHostToDevice);
    cudaMemcpy(d_dataB, h_dataB,ARRAY_BYTES, cudaMemcpyHostToDevice);
        cout << h_resultC[0] << endl;
        cout << h_resultC[ARRAY_SIZE-1] << endl;
    dim3 dimBlock(ARRAY_SIZE/8,1,1);
    dim3 dimGrid(1,1,1);
    VecAdd<<<dimGrid,dimBlock>>>(d_dataA, d_dataB, d_resultC);
        cout << h_resultC[0] << endl;
        cout << h_resultC[ARRAY_SIZE-1] << endl;
        cudaMemcpy(h_resultC,d_resultC ,ARRAY_BYTES,cudaMemcpyDeviceToHost);
        cout << h_resultC[0] << endl;
        cout << h_resultC[ARRAY_SIZE-1] << endl;
    return 0;
}

您是否先用ARRAY_SIZE线程启动它,然后用其中一半线程启动它?(或1/8)

您没有初始化d_resultC,所以d_resultC可能具有以前执行的结果。这可以解释这种行为,但也许不是。

在d_result_C上添加一个cudaMemset并告诉我们发生了什么。

我无法确定为什么内核处理的元素比预期的要多。它每个线程处理一个元素,所以处理的元素数量肯定应该是blockDim.x*gridDim.x。

不过,我想指出的是,编写使用"网格步长循环"的内核是一种很好的做法,这样它们就不会那么依赖于块和线程数。性能成本可以忽略不计,如果您对性能敏感,不同GPU的阻塞参数也会不同。

http://cudahandbook.to/15QbFWx

因此,您应该添加一个计数参数(要处理的元素数量),然后编写以下内容:

__global__ void VecAdd(float *d_dataA, float *d_dataB, float *d_resultC, int N)
{
    for ( int i = blockIdx.x*blockDim.x + threadIdx.x;
              i < N;
              i += blockDim.x*gridDim.x ) {
        d_resultC[i] = d_dataA[i] + d_dataB[i];
    }
}

正如上面提到的一些人。这可能是由于上次运行的剩余数据造成的。你没有释放你分配的内存可能是造成这种奇怪情况的原因。我认为您应该使用free释放主机上分配的阵列,并使用CudaFree 释放GPU上的内存

此外,我强烈建议您使用CudaMallocHost而不是malloc分配主机内存,并在程序结束时使用CudaFreeHost释放它们。这将为您提供快速复制。请参阅此处:CudaMallocHost

无论如何,不要忘记在C/C++程序上释放堆内存,无论是否使用CUDA。