【问题标题】:Crash on cudaMalloc when allocating 2D array分配二维数组时 cudaMalloc 崩溃
【发布时间】:2018-11-15 17:17:43
【问题描述】:

我正在尝试为 gPb 算法实现构建与图像中每个像素对应的 unsigned char 直方图数组。我无法解决的 cudaMalloc 调用崩溃。我已经查看了其他类似的问题,并且我总是测试之前的操作是否返回 cudaSuccess。这是我的代码:

首先我在我的类 CudaImage 的构造函数中分配这个结构:

bool CudaImage::create2DHistoArray()
{
    //preparing histograms
    m_LastCudaError = cudaMalloc((void**)&m_dHistograms, (m_Height + 2 * m_Scale) * sizeof(unsigned int*));

    if (m_LastCudaError != cudaSuccess)
        return false;

    //set all histograms to nullptr
    m_LastCudaError = cudaMemset(m_dHistograms, 0, (m_Height + 2 * m_Scale) * sizeof(unsigned int*));

    if (m_LastCudaError != cudaSuccess)
         return false;

    return true;
} 

然后在某个时候我会调用一个成员函数来分配一些 m_dHistograms[i],如下所示:

bool CudaImage::initializeHistoRange(int start, int stop)
{ 
    for (int i = start; i < stop; ++i) {
        m_LastCudaError = cudaMalloc((void**)&m_dHistograms[i], 256 * 2 * m_ArcNo * (m_Width + 2 * m_Scale) * sizeof(unsigned int));
        if (m_LastCudaError != cudaSuccess) {
            return false;
        }

        //set all pixels in the gradient images to 0
        m_LastCudaError = cudaMemset(m_dHistograms[i], 0, 256 * 2 * m_ArcNo * (m_Width + 2 * m_Scale) * sizeof(unsigned int));
        if (m_LastCudaError != cudaSuccess)
            return false;
        }

    return true;
}

最后一个函数中的第一个 cudaMalloc 在没有任何警告的情况下崩溃。使用 cuda-memcheck 运行时,我收到以下消息:

“应用程序在从主机取消引用统一内存时可能遇到错误。请在主机调试器下重新运行应用程序以捕获此类错误。”

谁能帮忙?另一个问题是数组分配是否正确实现。我不想从一开始就分配所有内存,因为它会太多,所以我在构造函数(第一个函数)中只分配指向数组行的指针,然后在应用程序中我在需要时分配内存并释放什么我不需要。

【问题讨论】:

标签: c++ cuda histogram


【解决方案1】:

您收到段错误是因为在主机代码中读取或修改 m_dHistograms[i] 的值是非法的,因为它是在设备内存中分配的。你需要做的是这样的:

bool CudaImage::initializeHistoRange(int start, int stop)
{ 
    for (int i = start; i < stop; ++i) {
        // Allocated memory
        unsigned int* p;
        m_LastCudaError = cudaMalloc((void**)&p, 256 * 2 * m_ArcNo * (m_Width + 2 * m_Scale) * sizeof(unsigned int));
        if (m_LastCudaError != cudaSuccess) {
            return false;
        }

        //set all pixels in the gradient images to 0
        m_LastCudaError = cudaMemset(p, 0, 256 * 2 * m_ArcNo * (m_Width + 2 * m_Scale) * sizeof(unsigned int));
        if (m_LastCudaError != cudaSuccess)
            return false;
        }

        // Transfer address of allocation to device    
        m_LastCudaError = cudaMemcpy(m_dHistograms + i, &p, sizeof(unsigned int *), cudaMemcpyHostToDevice);
        if (m_LastCudaError != cudaSuccess)
            return false;
        }
    return true;
}

[免责声明:从未编译或运行,使用风险自负]

这里分配地址存储在一个主机变量中,在分配和memset操作完成后,最终将其复制到设备数组中。这会导致每次分配额外的主机到设备内存传输的损失。

【讨论】:

  • 感谢您的回答。在我测试您的解决方案之前,请耐心等待。
【解决方案2】:

我在this stackoverflow answer 的帮助下找到了解决方案。代码如下:

bool CudaImage::initializeHistoRange(int start, int stop)
{
    for (int i = start; i < stop; ++i) {
        m_LastCudaError = cudaMalloc((void**)&m_hHistograms[i], 256 * 2 * m_ArcNo * (m_Width + 2 * m_Scale) * sizeof(unsigned int));
        if (m_LastCudaError != cudaSuccess) {
            return false;
        }

        cudaMemcpy(m_dHistograms, m_hHistograms, stop * sizeof(unsigned int*), cudaMemcpyHostToDevice);
        if (m_LastCudaError != cudaSuccess)
            return false;
    }

    return true;
}

bool CudaImage::create2DHistoArray()
{
    m_LastCudaError = cudaMalloc((void**)&m_dHistograms, (m_Height + 2 * m_Scale) * sizeof(unsigned int*));

    if (m_LastCudaError != cudaSuccess)
        return false;

    m_hHistograms = (unsigned int**)malloc((m_Height + 2 * m_Scale) * sizeof(unsigned int*));

    return true;
}

也就是说,我在主机成员中使用了一个额外的成员,它可以帮助我在设备中创建内存。算法运行时释放内存的代码是:

void CudaImage::deleteFromHistoMaps(int index) {

    //I need some more device memory
    if (index + m_Scale + 1 < m_Height + 2 * m_Scale) {
        initializeHistoRange(index + m_Scale + 1, index + m_Scale + 2);
    }

    //device memory is not needed anymore - free it
    if (index >= m_Scale + 1) {
        cudaFree(m_hHistograms[index - m_Scale - 1]);
        m_hHistograms[index - m_Scale - 1] = nullptr;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-09
    • 2013-07-29
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 2015-01-28
    相关资源
    最近更新 更多