CUDA - 内存限制 - 向量求和



我正在尝试学习 CUDA,以下代码对于值 N<= 16384 工作正常,但对于更大的值则失败(代码末尾的求和检查失败,c 值对于索引值 i>=16384 始终为 0)。

#include<iostream>
#include"cuda_runtime.h"
#include"../cuda_be/book.h"
#define N (16384)
__global__ void add(int *a,int *b,int *c)
{
    int tid = threadIdx.x + blockIdx.x * blockDim.x;
    if(tid<N)
    {
        c[tid] = a[tid] + b[tid];
        tid += blockDim.x * gridDim.x;
    }
}
int main()
{
    int a[N],b[N],c[N];
    int *dev_a,*dev_b,*dev_c;
    //allocate mem on gpu
    HANDLE_ERROR(cudaMalloc((void**)&dev_a,N*sizeof(int)));
    HANDLE_ERROR(cudaMalloc((void**)&dev_b,N*sizeof(int)));
    HANDLE_ERROR(cudaMalloc((void**)&dev_c,N*sizeof(int)));
    for(int i=0;i<N;i++)
    {
        a[i] = -i;
        b[i] = i*i;
    }
    HANDLE_ERROR(cudaMemcpy(dev_a,a,N*sizeof(int),cudaMemcpyHostToDevice));
    HANDLE_ERROR(cudaMemcpy(dev_b,b,N*sizeof(int),cudaMemcpyHostToDevice));
    system("PAUSE");
    add<<<128,128>>>(dev_a,dev_b,dev_c);
    //copy the array 'c' back from the gpu to the cpu
    HANDLE_ERROR( cudaMemcpy(c,dev_c,N*sizeof(int),cudaMemcpyDeviceToHost));
    system("PAUSE");
    bool success = true;
    for(int i=0;i<N;i++)
    {
        if((a[i] + b[i]) != c[i])
        {
            printf("Error in %d: %d + %d != %dn",i,a[i],b[i],c[i]);
            system("PAUSE");
            success = false;
        }
    }
    if(success) printf("We did it!n");
    cudaFree(dev_a);
    cudaFree(dev_b);
    cudaFree(dev_c);
    return 0;
}

我认为这是一个与共享内存相关的问题,但我无法想出一个很好的解释(可能缺乏知识)。您能否为我提供一个解释和解决方法,以运行大于 16384 的 N 值。这是我的 GPU 的规格:

General Info for device 0
Name: GeForce 9600M GT
Compute capability: 1.1
Clock rate: 1250000
Device copy overlap : Enabled
Kernel Execution timeout : Enabled
Mem info for device 0
Total global mem: 536870912
Total const mem: 65536
Max mem pitch: 2147483647
Texture Alignment 256
MP info about device 0
Multiproccessor count: 4
Shared mem per mp: 16384
Registers per mp: 8192
Threads in warp: 32
Max threads per block: 512
Max thread dimensions: (512,512,64)
Max grid dimensions: (65535,65535,1)

你可能打算写

while(tid<N)

if(tid<N)

您的共享内存没有用完,您的矢量数组正在复制到设备的全局内存中。如您所见,这比您需要的 196608 字节 (16384*4*3) 具有更多的可用空间。

您出现问题的原因是每个线程只执行一个加法操作,因此使用这种结构,您的向量的最大维度是内核启动中的块*线程参数,正如 tera 所指出的那样。通过纠正

if(tid<N)

while(tid<N)

在您的代码中,每个线程将在多个索引上执行其加法,并且将考虑整个数组。

有关内存层次结构和内存可以放置的各种不同位置的更多信息,您应该阅读 CUDA 工具包提供的CUDA_C_Programming_Guide.pdf的第 2.3 和 5.3 节。

希望有帮助。

如果 N 为:

#define N (33 * 1024) //value defined in Cuda by Examples

我在 Cuda 中通过示例找到的相同代码,但 N 的值不同。我认为 N 的 o 值不能是 33 * 1024。我必须更改参数块数和每个块的线程数。因为:

add<<<128,128>>>(dev_a,dev_b,dev_c); //16384 threads 

(128 * 128) <(33 * 1024) 所以我们发生了崩溃。

最新更新