内核上嵌套循环可能发生堆栈溢出

时间:2017-09-04 14:40:21

标签: cuda

我在下面的代码中遇到启动错误(这是一种模式缩减),经过一段时间之后,我注意到q的值小于39,但是如果它更高我得到启动错误。

在开始时我认为嵌套循环的数量过多,但在底部,我注意到即使使用额外的嵌套循环,q的较低值也可以。

在cuda调试模式下,不会报告错误。

问题

  • 是堆栈错误吗?
  • 假设q的最大值等于最大值 unsigned short还能做到吗?

尽可能简化代码:

#include "device_launch_parameters.h"
#include "stdlib.h"
#include "cuda.h"
#include <helper_functions.h>    // includes cuda.h and cuda_runtime_api.h
#include <helper_cuda.h>         // helper functions for CUDA error check
#include <stdio.h>
#include <cuda_runtime.h>
#include <stdio.h>

__global__ void loopTest(int q, int *ops, short* best) {
    int i, j, k, l, m, n, o, p;
    const int off(8);
    int maxSum(0), sum;
    const int qi = (q - blockDim.x * blockIdx.x + threadIdx.x);
    if (qi < 0) return;
    // qi, the upper for limit reduces as threadId increases
    for (i = 0; i < qi - off + 0; i++) 
        for (j = i + 1; j < qi - off + 1; j++)
            for (k = j + 1; k < qi - off + 2; k++)
                for (l = k + 1; l < qi - off + 3; l++)
                    for (m = l + 1; m < qi - off + 4; m++)
                        for (n = m + 1; n < qi - off + 5; n++)
                            for (o = n + 1; o < qi - off + 6; o++)
                                for (p = o + 1; p < qi - off + 7; p++)
                                    {
                                        sum = i + j + k + l + m + n + o + p;
                                        if (sum > maxSum) {
                                            best[0] = i;
                                            best[1] = j;
                                            best[2] = k;
                                            best[3] = l;
                                            best[4] = n;
                                            best[5] = m;
                                            best[6] = o;
                                            best[7] = p;
                                            maxSum = sum;
                                        }
                                    }
    ops[0] = maxSum;
    printf("max %d:", maxSum);
}

int main() {
    int *d_ops;
    short *d_best;
    cudaError_t cudaStatus;
    cudaStatus = cudaMalloc((void**)(&d_ops), sizeof(int));
    cudaStatus = cudaMalloc((void**)(&d_best), sizeof(short) * 8);

    // any q value smaller than 39 is fine, no error, but anything higher there is launch error

    loopTest << <1, 1 >> > (38, d_ops, d_best);

    cudaDeviceSynchronize();
    cudaStatus = cudaGetLastError();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "failure: %s", cudaGetErrorString(cudaStatus));
        return 99;
    }
    cudaStatus = cudaFree(d_ops);
    cudaStatus = cudaFree(d_best);
    cudaStatus = cudaDeviceReset();
    cudaStatus = cudaGetLastError();
    getchar();
    return cudaStatus;
}

背景

尽管非活动线程的频率很高(因为q valeu为intial_q - threadIdx.x),但它确实避免了来自主机的数据传输。这是我发现扫描其他群集分区的最佳方式。

规则

  • 所有元素必须低于单个集群(a.k.a硬集群)
  • 所有群集必须至少有一个元素
  • 向量中的元素位置是固定的

示例

(4个分区,10个元素,群集债券如下所示)

alt pat 1:1-1,2-2,3-3,4-10 (每个群集一个元素,除了最后一个元素{4,5,6,7,8,9和10}

alt pat 2:1-1,2-2,3-4,5-10 (与上述相同,但第4个群集的元素为{3和4},而最后一个群集的元素为{5,6,7,8,9和10}

...

alt pat x:1-1,2-2,3-9,10-10

alt pat x + 1:1-1,2-3,4-4,5-10

alt pat x + 2:1-1,2-3,4-5,6-10

...

alt pat y:1-7,8-8,9-9,10-10

最后一个可能的分区具有第一个集群中的最大元素数,因此任何其他集群都有一个元素

1 个答案:

答案 0 :(得分:0)

未指定的启动失败是由于内核超时。 这是由于处理成本较高且TDR窗口选项处于活动状态。 将其设置为关闭修复它。