Неправильный запуск функции CUDA NPP приводит к повреждению данных устройства

Я пишу код быстрого чтения JPEG, который я собираюсь использовать как часть большого проекта. Я решил использовать CUDA вместе с NPP для этой задачи, поскольку на NPP уже реализованы все функции кодирования и декодирования. Все работает нормально, пока я не попробую запустить инверсный DCT, используя nppiDCTQuantInv8x8LS_JPEG_16s8u_C1R_NEW функция. Кажется, это нарушает целостность кода. После запуска DCT отчет о нескольких вызовах cudaFree cudaErrorLaunchFailure, После использования NSIGHT CUDA Debugger я вижу, что запуск отчетов о функциях IDCT CUDA Grid launch failed ошибка. Что может быть вероятной причиной? Если я не использую отладчик NSIGHT, функция IDCT заканчивается на NPP_NO_ERROR, но все еще портит указатели устройства. Я прилагаю фрагменты кода, которые я считал актуальными, но я могу предоставить больше по запросу. У меня такое чувство, что в какой-то момент меня перепутали с указателями. Хотя я потратил значительное количество времени на проверку и отладку памяти на стороне хоста в отладчике.

Фактическая часть IDCT:

void CJPEGDecoder::InverseDCT(CJPGFile* file, NppiDCTState* pDCTState, CJPEGDeviceData* dataNPP)
{
    cudaError_t quantError, huffmanError, quantAllocError;
    NppStatus DCTstatus;
    Npp8u* deviceQuantizationTables;

    quantAllocError = cudaMalloc(&deviceQuantizationTables, 64 * file->m_quantizationTables.size());
    for (int i = 0; i < file->m_quantizationTables.size(); i++)
    {
        quantError = cudaMemcpyAsync(deviceQuantizationTables + i * 64, file->m_quantizationTables.at(i).aTable, 64, cudaMemcpyHostToDevice);
    }
    for (int i = 0; i < m_numComponent; i++)
    {
        int blockHeight = dataNPP[i].m_srcSize.height / 8;
        huffmanError = cudaMemcpyAsync(dataNPP[i].m_devDCT, m_hostDCT[i], dataNPP[i].m_DCTStep*blockHeight, cudaMemcpyHostToDevice);
    }

    // Inverse DCT
    for (int i = 0; i < m_numComponent; i++)
    {
        DCTstatus = nppiDCTQuantInv8x8LS_JPEG_16s8u_C1R_NEW(dataNPP[i].m_devDCT, dataNPP[i].m_DCTStep,
            dataNPP[i].m_srcImage, dataNPP[i].m_srcImageStep,
            deviceQuantizationTables + file->m_frameHeader.quantizationSelector[i] * 64,
            dataNPP[i].m_srcSize,
            pDCTState);
    }

    cudaFree(deviceQuantizationTables);
}

Ошибка при освобождении таблиц Хаффмана:

void CJPEGDecoder::HuffmanDealloc()
{
    NppStatus DCerror, ACerror;
    cudaError_t error;
    for (int i = 0; i < m_numComponent; i++)
    {
        DCerror = nppiDecodeHuffmanSpecFreeHost_JPEG(apHuffmanDCTable[i]); //NPP_OK
        ACerror = nppiDecodeHuffmanSpecFreeHost_JPEG(apHuffmanACTable[i]); //NPP_OK
        error = cudaFreeHost(m_hostDCT[i]); // cudaErrorLaunchFailure if DCT was launched, cudaSuccess otherwise
    }
}

Об ошибках при уничтожении CJPEGDeviceData:

void CJPEGDeviceData::ClearData()
{
    cudaError_t errorDCT, errorImg;
    m_DCTStep = 0;
    m_srcImageStep = 0;

    errorDCT = cudaFree(m_devDCT); // cudaErrorLaunchFailure if DCT was launched, cudaSuccess otherwise
    errorImg = cudaFree(m_srcImage); // cudaErrorLaunchFailure if DCT was launched, cudaSuccess otherwise

    m_allocated = false;
}

Фактический вызов для расчета dct и его окрестности:

void CJPEGWrapper::DecodeJPG()
{
    int numComponents = m_JPGFile->m_frameHeader.numberOfComponents;
    m_deviceData = new CJPEGDeviceData[numComponents];

    uint8_t maxV{ 0 }, maxH{ 0 };
    for (int i = 0; i < numComponents; i++)
    {
        uint8_t testH = m_JPGFile->m_frameHeader.samplingFactor[i] & 0x0F;
        uint8_t testV = m_JPGFile->m_frameHeader.samplingFactor[i] >> 4;
        if (testH > maxH)
            maxH = testH;
        if (testV > maxV)
            maxV = testV;
    }

    m_JPGdecoder.SetImgSize(m_JPGFile->m_frameHeader.width, m_JPGFile->m_frameHeader.height,numComponents);
    m_JPGdecoder.SetMaxMCUSize(maxH, maxV);

    for (int i = 0; i < numComponents; i++)
    {
        m_JPGdecoder.DecodeMCU(m_JPGFile->m_frameHeader.samplingFactor[i],m_deviceData[i]);
    }

    m_JPGdecoder.HuffmanAlloc(m_JPGFile);
    m_JPGdecoder.HuffmanDecode(m_JPGFile, m_deviceData);
    m_JPGdecoder.InverseDCT(m_JPGFile, m_pDCTState, m_deviceData); // IDCT is launched here
    m_JPGdecoder.HuffmanDealloc();
}

Класс CJPEGDeviceData:

class CJPEGDeviceData
{
public:
    NppiSize m_blockSize;
    NppiSize m_srcSize;
    Npp16s* m_devDCT;
    Npp32s m_DCTStep;

    Npp8u* m_srcImage;
    Npp32s m_srcImageStep;
public:
    CJPEGDeviceData();
    CJPEGDeviceData(const CJPEGDeviceData& object);
    CJPEGDeviceData(CJPEGDeviceData&& object);
    ~CJPEGDeviceData();

    void AllocDevicePointers(NppiSize blocksSize);
    void ClearData();
    bool IsAllocated() const;
private:
    bool m_allocated;
};

Может ли кто-нибудь помочь мне понять, что происходит и что я могу делать неправильно? cuda-memcheck не сообщает об ошибках вообще, даже когда я запускаю проблемную часть IDCT, я могу обнаружить только ошибки в отладчике VS. Я верю, что сам файл чтения работает правильно, я провел много тестов, поэтому начальные данные должны быть в порядке. Проблемы начинаются с данных устройства. Я также могу добавить, что запуск CUDA-профилировщика с включенным IDCT приведет к аварийному завершению работы приложения и выдаче ненулевого кода выхода. В противном случае все работает нормально.

0 ответов

Другие вопросы по тегам