CUDA可能使用';不足';共享内存

CUDA可能使用';不足';共享内存,cuda,gpu-shared-memory,Cuda,Gpu Shared Memory,我有一个简单的CUDA内核,可以通过基本的归约来进行向量累加。我正在扩展它,以便通过将其拆分为多个块来处理更大的数据。然而,我关于分配适当数量的共享内存供内核使用的假设由于非法内存访问而失败。当我增加这个限制时,它就消失了,但我想知道为什么。 下面是我所说的代码: 核心内核: __global__ static void vec_add(int *buffer, int numElem, // The actual number of ele

我有一个简单的CUDA内核,可以通过基本的归约来进行向量累加。我正在扩展它,以便通过将其拆分为多个块来处理更大的数据。然而,我关于分配适当数量的共享内存供内核使用的假设由于非法内存访问而失败。当我增加这个限制时,它就消失了,但我想知道为什么。 下面是我所说的代码:

核心内核:

    __global__ static
    void vec_add(int *buffer,
               int numElem,    //  The actual number of elements
               int numIntermediates)   //  The next power of two of numElem
    {
        extern __shared__ unsigned int interim[];

        int index = blockDim.x * blockIdx.x + threadIdx.x;

        //  Copy global intermediate values into shared memory.
        interim[threadIdx.x] =
          (index < numElem) ? buffer[index] : 0;

        __syncthreads();

        //  numIntermediates2 *must* be a power of two!
        for (unsigned int s = numIntermediates / 2; s > 0; s >>= 1) {
            if (threadIdx.x < s) {
                interim[threadIdx.x] += interim[threadIdx.x + s];
            }
            __syncthreads();
        }

        if (threadIdx.x == 0) {
            buffer[blockIdx.x] = interim[0];
        }
    }
我怀疑我的“临时”共享内存导致了非法内存访问,于是在下面的行中任意将共享内存增加了两倍:

reductionBlockSharedDataSize = 2 * numThreadsPerBlock * sizeof(unsigned int);
我的内核开始工作良好

我不明白的是——为什么我必须提供这个额外的共享内存来解决我的问题(暂时)

作为检验这个神奇数字的进一步实验,我用一个更大的数据集(6912个点)运行了我的代码。这一次,即使是2倍或4倍也帮不了我

Loop 1: numElem = 6912, numReductionThreads = 8192, numReductionBlocks = 8, numThreadsPerBlock = 1024, reductionBlockSharedDataSize = 16384

Loop 2: numElem = 6912, numReductionThreads = 8, numReductionBlocks = 1, numThreadsPerBlock = 8, reductionBlockSharedDataSize = 128
CUDA Error 77: an illegal memory access was encountered
但当我将共享内存大小增加了8倍时,问题又消失了


当然,我不能为越来越大的数据集随意选择这个比例因子,因为我很快就会用完48KB的共享内存限制。因此,我想知道一种合法的方法来解决我的问题。

感谢@havogt指出索引访问不足的问题。 问题是我使用了错误的参数作为vec_add方法的numentermedia。其目的是让内核在与线程数完全相同的数据点上操作,线程数应该一直是1024。 我使用numThreadsPerBlock作为参数修复了它:

vec_add <<< numReductionBlocks, numThreadsPerBlock, reductionBlockSharedDataSize >>>
        (buffer, numElem, numThreadsPerBlock);
vec\u add>
(缓冲区、numElem、numThreadsPerBlock);

您是否为循环计算了最大索引?快速看一看,我认为数学是这样的:
numIntermediates=2048
(1152的下一次幂为2),然后
s=1024
threadIdx.x
表示最大值
threadIdx.x=1023
。因此,最大的索引是2047,但是您只为1024个整数分配内存。谢谢@havogt:您指出了错误的来源!
Loop 1: numElem = 6912, numReductionThreads = 8192, numReductionBlocks = 8, numThreadsPerBlock = 1024, reductionBlockSharedDataSize = 16384

Loop 2: numElem = 6912, numReductionThreads = 8, numReductionBlocks = 1, numThreadsPerBlock = 8, reductionBlockSharedDataSize = 128
CUDA Error 77: an illegal memory access was encountered
vec_add <<< numReductionBlocks, numThreadsPerBlock, reductionBlockSharedDataSize >>>
        (buffer, numElem, numThreadsPerBlock);