英特尔 IPP ippsFree() 崩溃

Intel IPP ippsFree() crashes

我尝试了以下代码来检查 Intel IPP 调整图像大小/转换图像的速度,但它最后总是在 ippsFree(pSpec) 崩溃,我无法弄清楚原因。

#include <stdint.h>
#include <memory>
#include <Windows.h>
#include <time.h>

#include "ipp.h"

int main(...) {
    srand(time(NULL));

    int width = 640;
    int height = 480;
    int channels = 2;
    IppiResizeYUV422Spec* pSpec;
    IppiSize dstSize, srcSize;
    IppiPoint dstOffset = { 0, 0 };
    srcSize.width = width;
    srcSize.height = height;
    dstSize.width = 2 * width;
    dstSize.height = 2 * height;
    std::unique_ptr<unsigned char[]> sourceData;
    std::unique_ptr<unsigned char[]> destinationData;
    std::unique_ptr<unsigned char[]> destinationDataRGB;
    std::unique_ptr<unsigned char[]> workBuffer;

    sourceData.reset(new unsigned char[srcSize.width * srcSize.height * channels]);
    destinationData.reset(new unsigned char[dstSize.width * dstSize.height * channels]);
    destinationDataRGB.reset(new unsigned char[dstSize.width * dstSize.height * 3]);
    workBuffer.reset(new unsigned char[dstSize.width * dstSize.height * channels]);

    memset(sourceData.get(), 0, srcSize.width * srcSize.height * channels);
    memset(destinationData.get(), 0, dstSize.width * dstSize.height * channels);
    memset(workBuffer.get(), 0, dstSize.width * dstSize.height * channels);

    IppStatus error;
    int specSize = 0, initSize = 0, buffSize = 0;
    error = ippiResizeGetSize_8u(srcSize, dstSize, IppiInterpolationType::ippNearest, 0, &specSize, &initSize);

    pSpec = (IppiResizeYUV422Spec*) ippsMalloc_8u(specSize);
    error = ippiResizeYUV422NearestInit(srcSize, dstSize, pSpec);

    IppiRect srcRoi = { 0, 0, srcSize.width, srcSize.height };

    int64_t timerIPP9 = 0;
    LARGE_INTEGER start, end;
    LARGE_INTEGER tps;
    QueryPerformanceFrequency(&tps);

    for (unsigned int index = 0; index < 100; ++index) {
        for (unsigned int imageIdx = 0; imageIdx < srcSize.width * srcSize.height * channels; ++imageIdx) {
            sourceData.get()[imageIdx] = (rand() & 0xFF);
        }

        QueryPerformanceCounter(&start);
        error = ippiResizeYUV422Nearest_8u_C2R(
            sourceData.get(),
            srcSize.width * channels,
            destinationData.get(),
            dstSize.width * channels,
            dstOffset,
            dstSize,
            pSpec,
            workBuffer.get());
        QueryPerformanceCounter(&end);

        timerIPP9 += end.QuadPart - start.QuadPart;

        QueryPerformanceCounter(&start);
        ippiYCbCr422ToRGB_8u_C2C3R(destinationData.get(), dstSize.width * channels, destinationDataRGB.get(), dstSize.width * 3, dstSize);
        QueryPerformanceCounter(&end);

        timerIPP9 += end.QuadPart - start.QuadPart;
        printf("Test: %d, time: %d ms\r", index, timerIPP9 * 1000 / tps.QuadPart);
    }

    ippsFree(pSpec);
    printf("\n");
    printf("Time taken: %d ms\n", timerIPP9 * 1000 / tps.QuadPart);
    system("Pause");
    return 0;
}

我只是将随机数据传输到转换器中,但它应该能够处理噪声(因为它仍然是一个有效图像)。

我想我解开了谜题...

您需要做的就是替换以下类似代码:

error = ippiResizeGetSize_8u(srcSize, dstSize, IppiInterpolationType::ippNearest, 0, &specSize, &initSize);

与以下一个:

error = ippiResizeYUV422GetSize(srcSize, dstSize, IppiInterpolationType::ippNearest, 0, &specSize, &initSize);

根据 IPP 文档:

Description This function initializes the IppiResizeYUV422Spec structure for the resize algorithm with the nearest neighbor interpolation method.
To calculate the size of the spec structure object, call the ippiResizeYUV422GetSize function.

参见:http://hpc.ipp.ac.cn/wp-content/uploads/2015/12/documentation_2016/en/ipp/common/ipp_manual/GUID-15B51AB0-7F73-4E13-AC81-753259CE0E2C.htm

执行ippiResizeYUV422GetSize时,specSize的值等于11776.
执行ippiResizeGetSize_8u时,specSize的值等于9240.
较小的分配大小会导致堆损坏。