Сбой на cudaMalloc при выделении 2D-массива - PullRequest
0 голосов
/ 13 ноября 2018

Я пытаюсь построить массивы гистограмм неподписанного символа, соответствующие каждому пикселю в изображении для реализации алгоритма gPb.У меня сбой при вызове 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 я получаю следующее сообщение:

"Возможно, в приложении произошла ошибка при разыменовании единой памяти с хоста. Пожалуйста, перезапустите приложение под отладчиком хоста, чтобы перехватить такие ошибки."

Кто-нибудь может помочь?Другой вопрос будет, правильно ли реализовано распределение массива.Я не хочу выделять всю память с самого начала, потому что это будет слишком много, поэтому я выделяю в конструкторе (первая функция) только указатели на строки массива, а затем в приложении я выделяю память, когда мне это нужно, и освобождаюМне не нужно.

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Решение, которое я нашел, с помощью этого ответа stackoverflow . Код выглядит следующим образом:

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;
}

То есть я использую дополнительный элемент в элементе host, который помогает мне создать память в устройстве. Код для освобождения памяти во время работы алгоритма:

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;
    }
}
0 голосов
/ 13 ноября 2018

Вы получаете segfaults, потому что считывать или изменять значение 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;
}

[заявление об отказе: никогда не компилируется и не запускается, используйте на свой страх и риск]

Здесь адрес распределения хранится в переменной хоста, котораянаконец, копируется в массив устройств после выполнения операций выделения и памяти.Это влечет за собой штраф за передачу дополнительного хоста в память устройства за выделение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...