【问题标题】:cuda - can't access blockDim.x?cuda - 无法访问 blockDim.x?
【发布时间】:2017-11-04 18:48:37
【问题描述】:

我正在开发一个处理 2D 图像的 cuda 程序。

问题是当我尝试访问blockDim.xblockId.x时,内核总是无法启动和输出unknown error

此外,如果我使用3x5 图像,我可以访问threadId.x,而我不能使用2048x2048 图像。

当我使用PyCuda 时,我的内核代码运行正常,但现在我必须切换到cuda C

我认为问题可能与

  • 我传递数组指针的方式,cudaMalloc 有问题
  • 我的块大小和网格大小的配置(但相同的配置在PyCuda 中运行良好,所以我不知道如何更正它)。

我使用cuda-memcheck,得到unknown error 30,我搜索了解决方案,但没有任何有用的信息。

__global__ void extractor(const unsigned char* in, unsigned char* out, int* debug)
{
    int idx = (threadIdx.x) + blockDim.x * blockIdx.x ;
    debug[idx] = threadIdx.x; // debug variable is used for debugging
}

int main(int arg, char* args[])
{
    // ...
    int size = w*h; // w is image width and h is image height
    unsigned char *in = 0;
    unsigned char *out = 0;
    int* debug = 0;

    // Allocate GPU buffers for the images
    cudaMalloc((void**)&in, size * sizeof(unsigned char));
    cudaMalloc((void**)&out, num_sample_per_point * size * sizeof(unsigned char));
    cudaMalloc((void**)&debug, size * sizeof(int));

    // Copy image data from host memory to GPU buffers.
    cudaMemcpy(in, &img_data[0], size * sizeof(unsigned char),cudaMemcpyHostToDevice);

    dim3 b_dim(BLOCK_SIZE, 1, 1);   // (1024, 1, 1)
    dim3 g_dim(int(w*h/BLOCK_SIZE)+1, 1, 1);    // (4097, 1, 1)
    extractor<<<g_dim, b_dim>>>(in, out, debug);

    // clean up code and processing result
}

现在我无法获得预期的索引,所以我无法在内核中进行处理,可能是什么问题?


编辑

我想使用一维索引,这意味着我假设图像数组是一个“扁平化”的一维数组并进行索引。


编辑

添加线程检查后,还是有问题。

__global__ void extractor(const unsigned char* in, unsigned char* out, int* debug)
{
    int idx = (threadIdx.x) + blockDim.x * blockIdx.x ;
    int y; int x;
    int temp_x; int temp_y; int temp_idx;
    int check = width*height;
    if (idx < check) {
        debug[0] = 1;    // get kernel launch failed "unknown error"
    }
}

我尝试将debug[0]=1; 表达式放在线程检查块和块外,它们都得到相同的错误。

所以我怀疑 memalloc 没有正确完成?

顺便说一句,我用了nvprof,它说

=22344== Warning: Found 2 invalid records in the result.
==22344== Warning: This can happen if device ran out of memory or if a device kernel was stopped due to an assertion.

编辑

完整代码:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <cmath>
#include <iostream>

#include "PNG.h"

#define L 3
#define INC1 1
#define INC2 1
#define R_IN 2
#define N_P 4
#define BLOCK_SIZE 1024
#define PI 3.14159265358979323846

using namespace std;

__global__ void extractor(const unsigned char* in, unsigned char* out, int* debug, int* disX, int* disY, int width, int height, int pad, int num_sample)
{
    int idx = (threadIdx.x) + blockDim.x * blockIdx.x ;
    int y; int x;
    int temp_x; int temp_y; int temp_idx;
    int check = width*height;

       if (idx < check) {
        debug[idx] = threadIdx.x;
        y = idx/width;
        x = idx%width;
            if ((x < pad) || (x >= (width-pad)) || (y < pad) || (y >= (height-pad))) {
                // need padding
                for (int i = 0; i < num_sample; ++i){
                    temp_x = x + disX[i];
                    temp_y = y + disY[i];

                    if (!((temp_x < 0)||(temp_x > (width-1)) || (temp_y < 0) ||(temp_y>(height-1)))) {
                    temp_idx = temp_y*width + temp_x;   // sampled index
                    out[(idx*num_sample)+i] = in[temp_idx]; // copy sampled value to result
                }
                }
            } else {
                for (int i = 0; i < num_sample; ++i)
                {
                    temp_x = x + disX[i];
                    temp_y = y + disY[i];
                    temp_idx = temp_y*width + temp_x;   // sampled index
                    out[(idx*num_sample)+i] = in[temp_idx]; // copy sampled value to result
                }
            }
       }
  }

vector<int> getCirclePos() {
    int r = 0;
    vector <int> circlePos;
    while (!(r>(L/2))) {
        circlePos.push_back(r);
        if (r < R_IN) r += INC1;
        else r += INC2;
    }
    cout << "circlePos:" << endl;
    for (auto i = circlePos.begin(); i != circlePos.end(); ++i)
    {cout << *i << ' ';}
    cout << endl;
    return circlePos;
}

int main(int arg, char* args[])
{
    cudaError_t cudaStatus;
    vector<int> circlePos = getCirclePos();

    // get disX, disY
    int num_sample_per_point = circlePos.size() * N_P;
    int* disX = new int[num_sample_per_point];
    int* disY = new int[num_sample_per_point];
    int r; int cnt = 0;
    for (int i = 0; i < circlePos.size(); ++i)
    {
        r = circlePos[i];
        float angle;
        for (int j = 0; j < N_P; ++j)
        {
            angle = j*360.0/N_P;
            disX[cnt] = r*cos(angle*M_PI/180.0);
            disY[cnt] = r*sin(angle*M_PI/180.0);
            // cout nvpro   << disX[cnt] << "|" << disY[cnt]<< endl;

            cnt++;
        }
    }

    PNG inPng("test.png");
    // PNG outPng;
    // outPng.Create(inPng.w, inPng.h);

    //store width and height so we can use them for our output image later
    const unsigned int w = inPng.w;
    const unsigned int h = inPng.h;
    cout << "w: " << w << " h: " << h << endl;
    //4 because there are 4 color channels R, G, B, and A
    int size = w * h;

    unsigned char *in = 0;
    unsigned char *out = 0;
    int* debug = 0;

    // Allocate GPU buffers for the images
    cudaMalloc((void**)&in, size * sizeof(unsigned char));
    cudaMalloc((void**)&out, num_sample_per_point * size * sizeof(unsigned char));
    cudaMalloc((void**)&debug, size * sizeof(int));


    vector<unsigned char> img_data;
    for (int i = 0; i < size; ++i)
    {
        img_data.push_back(inPng.data[i*4]);
    }

    // debug
    cout << "========= img_data ==========" << endl;
    for (int i = 0; i < size; ++i)
    {
        cout << int(img_data[i]) << "," ;
    }
    cout << endl;

    // Copy image data from host memory to GPU buffers.
    cudaMemcpy(in, &img_data[0], size * sizeof(unsigned char), cudaMemcpyHostToDevice);

    //free the input image because we do not need it anymore
    inPng.Free();

    // Launch a kernel on the GPU with one thread for each element.
    dim3 b_dim(BLOCK_SIZE, 1, 1);   // (1024, 1, 1)
    dim3 g_dim(int(w*h/BLOCK_SIZE)+1, 1, 1);    // (4097, 1, 1)
    int pad = L/2;

    // __global__ void extractor(const unsigned char* in, unsigned char* out, vector<int> disX, vector<int> disY, int width, int height, int pad, int num_sample)
    extractor<<<g_dim, b_dim>>>(in, out, debug, disX, disY, w, h, pad, num_sample_per_point);

    cudaStatus = cudaGetLastError();
    if (cudaStatus != cudaSuccess)
    {
        std::cout << "Kernel launch failed: " << cudaGetErrorString(cudaStatus) << std::endl;
        cudaFree(in);
        cudaFree(out);
        cudaFree(debug);
        exit(1);
    }

    auto tmp = new unsigned char[size*num_sample_per_point];
    auto tmp_debug = new int [size];

    cudaMemcpy(tmp_debug, debug, size * sizeof(int), cudaMemcpyDeviceToHost);
    cudaMemcpy(tmp, out, num_sample_per_point * size * sizeof(unsigned char), cudaMemcpyDeviceToHost);

    cout << "========= out =========" << endl;
    for (int i = 0; i < size*num_sample_per_point; ++i)
    {
        cout << int(tmp[i]) << ", ";
    }
    cout << endl;

    cout << "========debug=======" << endl;
    for (int i = 0; i < size; ++i)
    {
        cout << tmp_debug[i] << ", ";
    }
    cout << endl;

    cudaFree(in);
    cudaFree(out);
    cudaFree(debug);

    delete[] tmp; delete[] tmp_debug;

    return 0;
}

【问题讨论】:

    标签: cuda


    【解决方案1】:

    这(根据您的评论)定义了每个块 1024 个线程:

    dim3 b_dim(BLOCK_SIZE, 1, 1);   // (1024, 1, 1)
    

    根据您的问题文本,wh 在失败的情况下均为 2048,因此:

    dim3 g_dim(int(w*h/BLOCK_SIZE)+1, 1, 1);    // (4097, 1, 1)
    

    正如您在评论中指出的那样,正在创建 4097 个区块。

    4097 块 1024 个线程,每个块总共 4195328 个线程,但您的分配大小仅提供 2048*2048 个元素,或总共 4194304 个元素。所以你启动了 4195328 个线程,只有 4194304 个元素,剩下 1024 个线程。

    那么这 1024 个额外的线程有什么作用呢?他们仍然运行内核代码并尝试访问您的 debug 数组超出分配空间的末尾。

    这会导致 C 和 C++ 中的未定义行为。

    解决此问题的习惯方法是将问题大小传递给内核并在内核代码中添加“线程检查”,如下所示:

    __global__ void extractor(const unsigned char* in, unsigned char* out, int* debug, int n)
    {
        int idx = (threadIdx.x) + blockDim.x * blockIdx.x ;
        if (idx < n)
          debug[idx] = threadIdx.x; // debug variable is used for debugging
    }
    

    这会阻止“额外”线程做任何事情。

    如果您在cuda 标签上搜索“线程检查”,您会发现许多其他类似问题的示例。

    例如,根据您显示的代码片段,以下对我来说运行没有错误:

    $ cat t147.cu
    const int width = 2048;
    const int height = 2048;
    const int BLOCK_SIZE = 1024;
    __global__ void extractor(const unsigned char* in, unsigned char* out, int* debug)
    {
        int idx = (threadIdx.x) + blockDim.x * blockIdx.x ;
    //    int y; int x;
    //    int temp_x; int temp_y; int temp_idx;
        int check = width*height;
        if (idx < check) {
            debug[idx] = 1;    // get kernel launch failed "unknown error"
        }
    }
    int main(int arg, char* args[])
    {
    
        const int w = width;
        const int h = height;
        const int num_sample_per_point = 1;
        int size = w*h; // w is image width and h is image height
        unsigned char *in = 0;
        unsigned char *out = 0;
        int* debug = 0;
    
        // Allocate GPU buffers for the images
        cudaMalloc((void**)&in, size * sizeof(unsigned char));
        cudaMalloc((void**)&out, num_sample_per_point * size * sizeof(unsigned char));
        cudaMalloc((void**)&debug, size * sizeof(int));
    
        // Copy image data from host memory to GPU buffers.
    //    cudaMemcpy(in, &img_data[0], size * sizeof(unsigned char),cudaMemcpyHostToDevice);
    
        dim3 b_dim(BLOCK_SIZE, 1, 1);   // (1024, 1, 1)
        dim3 g_dim(int(w*h/BLOCK_SIZE)+1, 1, 1);    // (4097, 1, 1)
        extractor<<<g_dim, b_dim>>>(in, out, debug);
        cudaDeviceSynchronize();
    }
    $ nvcc -arch=sm_61 -o t147 t147.cu
    $ cuda-memcheck ./t147
    ========= CUDA-MEMCHECK
    ========= ERROR SUMMARY: 0 errors
    $
    

    在您的完整代码中,您的内核中只是存在非法访问问题。我已经对其进行了修改以消除对 PNG 的依赖,如果我们省略除调试设置以外的内核代码,它运行良好。但是,如果我们包含您的内核代码并使用cuda-memcheck 运行,我们会得到各种越界访问。以后可以使用here描述的方法来调试这些:

    $ cat t146.cu
    #include <cmath>
    #include <iostream>
    #include <vector>
    
    #define L 3
    #define INC1 1
    #define INC2 1
    #define R_IN 2
    #define N_P 4
    #define BLOCK_SIZE 1024
    #define PI 3.14159265358979323846
    
    using namespace std;
    
    __global__ void extractor(const unsigned char* in, unsigned char* out, int* debug, int* disX, int* disY, int width, int height, int pad, int num_sample)
    {
        int idx = (threadIdx.x) + blockDim.x * blockIdx.x ;
        int y; int x;
        int temp_x; int temp_y; int temp_idx;
        int check = width*height;
    
           if (idx < check) {
            debug[idx] = threadIdx.x;
            y = idx/width;
            x = idx%width;
    #ifdef  FAIL
                if ((x < pad) || (x >= (width-pad)) || (y < pad) || (y >= (height-pad))) {
                    // need padding
                    for (int i = 0; i < num_sample; ++i){
                        temp_x = x + disX[i];
                        temp_y = y + disY[i];
    
                        if (!((temp_x < 0)||(temp_x > (width-1)) || (temp_y < 0) ||(temp_y>(height-1)))) {
                        temp_idx = temp_y*width + temp_x;   // sampled index
                        out[(idx*num_sample)+i] = in[temp_idx]; // copy sampled value to result
                    }
                    }
                } else {
                    for (int i = 0; i < num_sample; ++i)
                    {
                        temp_x = x + disX[i];
                        temp_y = y + disY[i];
                        temp_idx = temp_y*width + temp_x;   // sampled index
                        out[(idx*num_sample)+i] = in[temp_idx]; // copy sampled value to result
                    }
                }
    #endif
           }
      }
    
    vector<int> getCirclePos() {
        int r = 0;
        vector <int> circlePos;
        while (!(r>(L/2))) {
            circlePos.push_back(r);
            if (r < R_IN) r += INC1;
            else r += INC2;
        }
        cout << "circlePos:" << endl;
        for (auto i = circlePos.begin(); i != circlePos.end(); ++i)
        {//cout << *i << ' ';
          }
        cout << endl;
        return circlePos;
    }
    
    int main(int arg, char* args[])
    {
        cudaError_t cudaStatus;
        vector<int> circlePos = getCirclePos();
    
        // get disX, disY
        int num_sample_per_point = circlePos.size() * N_P;
        int* disX = new int[num_sample_per_point];
        int* disY = new int[num_sample_per_point];
        int r; int cnt = 0;
        for (int i = 0; i < circlePos.size(); ++i)
        {
            r = circlePos[i];
            float angle;
            for (int j = 0; j < N_P; ++j)
            {
                angle = j*360.0/N_P;
                disX[cnt] = r*cos(angle*M_PI/180.0);
                disY[cnt] = r*sin(angle*M_PI/180.0);
                // cout nvpro   << disX[cnt] << "|" << disY[cnt]<< endl;
    
                cnt++;
            }
        }
    
        const unsigned int w = 2048;
        const unsigned int h = 2048;
        cout << "w: " << w << " h: " << h << endl;
        //4 because there are 4 color channels R, G, B, and A
        int size = w * h;
    
        unsigned char *in = 0;
        unsigned char *out = 0;
        int* debug = 0;
    
        // Allocate GPU buffers for the images
        cudaMalloc((void**)&in, size * sizeof(unsigned char));
        cudaMalloc((void**)&out, num_sample_per_point * size * sizeof(unsigned char));
        cudaMalloc((void**)&debug, size * sizeof(int));
    
    
        vector<unsigned char> img_data;
        for (int i = 0; i < size; ++i)
        {
            img_data.push_back(0);
        }
    
        // debug
        cout << "========= img_data ==========" << endl;
        for (int i = 0; i < size; ++i)
        {
     //       cout << int(img_data[i]) << "," ;
        }
        cout << endl;
    
        // Copy image data from host memory to GPU buffers.
        cudaMemcpy(in, &img_data[0], size * sizeof(unsigned char), cudaMemcpyHostToDevice);
    
    
        // Launch a kernel on the GPU with one thread for each element.
        dim3 b_dim(BLOCK_SIZE, 1, 1);   // (1024, 1, 1)
        dim3 g_dim(int(w*h/BLOCK_SIZE)+1, 1, 1);    // (4097, 1, 1)
        int pad = L/2;
    
        // __global__ void extractor(const unsigned char* in, unsigned char* out, vector<int> disX, vector<int> disY, int width, int height, int pad, int num_sample)
        extractor<<<g_dim, b_dim>>>(in, out, debug, disX, disY, w, h, pad, num_sample_per_point);
    
        cudaStatus = cudaGetLastError();
        if (cudaStatus != cudaSuccess)
        {
            std::cout << "Kernel launch failed: " << cudaGetErrorString(cudaStatus) << std::endl;
            cudaFree(in);
            cudaFree(out);
            cudaFree(debug);
            exit(1);
        }
    
        auto tmp = new unsigned char[size*num_sample_per_point];
        auto tmp_debug = new int [size];
    
        cudaMemcpy(tmp_debug, debug, size * sizeof(int), cudaMemcpyDeviceToHost);
        cudaMemcpy(tmp, out, num_sample_per_point * size * sizeof(unsigned char), cudaMemcpyDeviceToHost);
    
        cout << "========= out =========" << endl;
        for (int i = 0; i < size*num_sample_per_point; ++i)
        {
       //     cout << int(tmp[i]) << ", ";
        }
        cout << endl;
    
        cout << "========debug=======" << endl;
        for (int i = 0; i < size; ++i)
        {
         //   cout << tmp_debug[i] << ", ";
        }
        cout << endl;
    
        cudaFree(in);
        cudaFree(out);
        cudaFree(debug);
    
        delete[] tmp; delete[] tmp_debug;
    
        return 0;
    }
    $ nvcc -std=c++11 -o t146 t146.cu -arch=sm_61 -lineinfo
    t146.cu(18): warning: variable "y" was set but never used
    
    t146.cu(18): warning: variable "x" was set but never used
    
    t146.cu(19): warning: variable "temp_x" was declared but never referenced
    
    t146.cu(19): warning: variable "temp_y" was declared but never referenced
    
    t146.cu(19): warning: variable "temp_idx" was declared but never referenced
    
    t146.cu(18): warning: variable "y" was set but never used
    
    t146.cu(18): warning: variable "x" was set but never used
    
    t146.cu(19): warning: variable "temp_x" was declared but never referenced
    
    t146.cu(19): warning: variable "temp_y" was declared but never referenced
    
    t146.cu(19): warning: variable "temp_idx" was declared but never referenced
    
    $ cuda-memcheck ./t146
    ========= CUDA-MEMCHECK
    circlePos:
    
    w: 2048 h: 2048
    ========= img_data ==========
    
    ========= out =========
    
    ========debug=======
    
    ========= ERROR SUMMARY: 0 errors
    $ nvcc -std=c++11 -o t146 t146.cu -arch=sm_61 -lineinfo -DFAIL
    $ cuda-memcheck ./t146
    ...
    ========= Invalid __global__ read of size 4
    =========     at 0x00000418 in /home/ubuntu/bobc/misc/t146.cu:41:extractor(unsigned char const *, unsigned char*, int*, int*, int*, int, int, int, int)
    =========     by thread (197,0,0) in block (17,0,0)
    =========     Address 0x00c8b290 is out of bounds
    =========     Saved host backtrace up to driver entry point at kernel launch time
    =========     Host Frame:/usr/lib/x86_64-linux-gnu/libcuda.so.1 (cuLaunchKernel + 0x2c5) 
    ...
    (and much more output like this)
    

    上面的输出指向代码中的第41行,从disX读取。

    事实证明,您的 disX 是一个主机分配的变量:

    int* disX = new int[num_sample_per_point];
    

    但您正试图将其传递给设备代码:

    extractor<<<g_dim, b_dim>>>(in, out, debug, disX, disY, w, h, pad, num_sample_per_point);
                                                ^^^^
    

    这完全被打破了。你不能在 CUDA 中做到这一点。您需要制作该变量的设备副本,以及disY 当我修复该问题时,修改后的代码对我来说运行没有错误:

    $ cat t146.cu
    #include <cmath>
    #include <iostream>
    #include <vector>
    
    #define L 3
    #define INC1 1
    #define INC2 1
    #define R_IN 2
    #define N_P 4
    #define BLOCK_SIZE 1024
    #define PI 3.14159265358979323846
    
    using namespace std;
    
    __global__ void extractor(const unsigned char* in, unsigned char* out, int* debug, int* disX, int* disY, int width, int height, int pad, int num_sample)
    {
        int idx = (threadIdx.x) + blockDim.x * blockIdx.x ;
        int y; int x;
        int temp_x; int temp_y; int temp_idx;
        int check = width*height;
    
           if (idx < check) {
            debug[idx] = threadIdx.x;
            y = idx/width;
            x = idx%width;
    #ifdef  FAIL
                if ((x < pad) || (x >= (width-pad)) || (y < pad) || (y >= (height-pad))) {
                    // need padding
                    for (int i = 0; i < num_sample; ++i){
                        temp_x = x + disX[i];
                        temp_y = y + disY[i];
    
                        if (!((temp_x < 0)||(temp_x > (width-1)) || (temp_y < 0) ||(temp_y>(height-1)))) {
                        temp_idx = temp_y*width + temp_x;   // sampled index
                        out[(idx*num_sample)+i] = in[temp_idx]; // copy sampled value to result
                    }
                    }
                } else {
                    for (int i = 0; i < num_sample; ++i)
                    {
                        temp_x = x + disX[i];
                        temp_y = y + disY[i];
                        temp_idx = temp_y*width + temp_x;   // sampled index
                        out[(idx*num_sample)+i] = in[temp_idx]; // copy sampled value to result
                    }
                }
    #endif
           }
      }
    
    vector<int> getCirclePos() {
        int r = 0;
        vector <int> circlePos;
        while (!(r>(L/2))) {
            circlePos.push_back(r);
            if (r < R_IN) r += INC1;
            else r += INC2;
        }
        cout << "circlePos:" << endl;
        for (auto i = circlePos.begin(); i != circlePos.end(); ++i)
        {//cout << *i << ' ';
          }
        cout << endl;
        return circlePos;
    }
    
    int main(int arg, char* args[])
    {
        cudaError_t cudaStatus;
        vector<int> circlePos = getCirclePos();
    
        // get disX, disY
        int num_sample_per_point = circlePos.size() * N_P;
        int* disX = new int[num_sample_per_point];
        int* disY = new int[num_sample_per_point];
        int r; int cnt = 0;
        for (int i = 0; i < circlePos.size(); ++i)
        {
            r = circlePos[i];
            float angle;
            for (int j = 0; j < N_P; ++j)
            {
                angle = j*360.0/N_P;
                disX[cnt] = r*cos(angle*M_PI/180.0);
                disY[cnt] = r*sin(angle*M_PI/180.0);
                // cout nvpro   << disX[cnt] << "|" << disY[cnt]<< endl;
    
                cnt++;
            }
        }
    
        int *d_disX, *d_disY;
        cudaMalloc(&d_disX, num_sample_per_point*sizeof(int));
        cudaMalloc(&d_disY, num_sample_per_point*sizeof(int));
        cudaMemcpy(d_disX, disX, num_sample_per_point*sizeof(int), cudaMemcpyHostToDevice);
        cudaMemcpy(d_disY, disY, num_sample_per_point*sizeof(int), cudaMemcpyHostToDevice);
        const unsigned int w = 2048;
        const unsigned int h = 2048;
        cout << "w: " << w << " h: " << h << endl;
        //4 because there are 4 color channels R, G, B, and A
        int size = w * h;
    
        unsigned char *in = 0;
        unsigned char *out = 0;
        int* debug = 0;
    
        // Allocate GPU buffers for the images
        cudaMalloc((void**)&in, size * sizeof(unsigned char));
        cudaMalloc((void**)&out, num_sample_per_point * size * sizeof(unsigned char));
        cudaMalloc((void**)&debug, size * sizeof(int));
    
    
        vector<unsigned char> img_data;
        for (int i = 0; i < size; ++i)
        {
            img_data.push_back(0);
        }
    
        // debug
        cout << "========= img_data ==========" << endl;
        for (int i = 0; i < size; ++i)
        {
     //       cout << int(img_data[i]) << "," ;
        }
        cout << endl;
    
        // Copy image data from host memory to GPU buffers.
        cudaMemcpy(in, &img_data[0], size * sizeof(unsigned char), cudaMemcpyHostToDevice);
    
    
        // Launch a kernel on the GPU with one thread for each element.
        dim3 b_dim(BLOCK_SIZE, 1, 1);   // (1024, 1, 1)
        dim3 g_dim(int(w*h/BLOCK_SIZE)+1, 1, 1);    // (4097, 1, 1)
        int pad = L/2;
    
        // __global__ void extractor(const unsigned char* in, unsigned char* out, vector<int> disX, vector<int> disY, int width, int height, int pad, int num_sample)
        extractor<<<g_dim, b_dim>>>(in, out, debug, d_disX, d_disY, w, h, pad, num_sample_per_point);
    
        cudaStatus = cudaGetLastError();
        if (cudaStatus != cudaSuccess)
        {
            std::cout << "Kernel launch failed: " << cudaGetErrorString(cudaStatus) << std::endl;
            cudaFree(in);
            cudaFree(out);
            cudaFree(debug);
            exit(1);
        }
    
        auto tmp = new unsigned char[size*num_sample_per_point];
        auto tmp_debug = new int [size];
    
        cudaMemcpy(tmp_debug, debug, size * sizeof(int), cudaMemcpyDeviceToHost);
        cudaMemcpy(tmp, out, num_sample_per_point * size * sizeof(unsigned char), cudaMemcpyDeviceToHost);
    
        cout << "========= out =========" << endl;
        for (int i = 0; i < size*num_sample_per_point; ++i)
        {
       //     cout << int(tmp[i]) << ", ";
        }
        cout << endl;
    
        cout << "========debug=======" << endl;
        for (int i = 0; i < size; ++i)
        {
         //   cout << tmp_debug[i] << ", ";
        }
        cout << endl;
    
        cudaFree(in);
        cudaFree(out);
        cudaFree(debug);
    
        delete[] tmp; delete[] tmp_debug;
    
        return 0;
    }
    $ nvcc -std=c++11 -o t146 t146.cu -arch=sm_61 -lineinfo -DFAIL
    $ cuda-memcheck ./t146
    ========= CUDA-MEMCHECK
    circlePos:
    
    w: 2048 h: 2048
    ========= img_data ==========
    
    ========= out =========
    
    ========debug=======
    
    ========= ERROR SUMMARY: 0 errors
    $
    

    【讨论】:

    • 您好,感谢您的回复。我已经按照你说的修改了代码,但似乎即使我进行线程检查,我也无法访问内核中的debug 变量。请查看我的编辑。
    • 您需要提供minimal reproducible example 我不知道widthheight 是什么。它应该是一个完整的代码,我可以复制、粘贴和编译,无需添加任何内容或更改任何内容。
    • 添加到问题详细信息。提前致谢。
    • 我无法编译它。我没有 PNG.h 无论如何,您应该提供最少的代码。
    • 您正在将主机指针 disXdisY 传递给设备代码。这是 CUDA 中的一个基本错误。
    猜你喜欢
    • 2015-06-28
    • 2017-12-25
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 2017-06-26
    • 2021-03-25
    • 2015-05-02
    • 2022-01-18
    相关资源
    最近更新 更多