0

I tried following code to check how fast the Intel IPP is for resizing / converting images, but it keeps on crashing at ippsFree(pSpec) at the end, and I cannot figure out, why.

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

I am just piping random data into the converter, but it should be able to deal with the noise (as it still is a valid image).

SinisterMJ
  • 3,425
  • 2
  • 33
  • 53
  • I am using the latest Intel IPP 2017.1.143 – SinisterMJ Jan 02 '17 at 14:11
  • Have you tried freeing right after allocation? And it doesn't look like you're checking error responses. (Disclaimer: I've never used Intel IPP) – owacoder Jan 02 '17 at 14:15
  • I've never used Intel IPP either. Could the problem be that you somehow write outside the `pSpec` buffer, which it then notices when calling `ippsFree`? – simon Jan 02 '17 at 14:18
  • I allocate the pSpec with around 9000 bytes, and later the runtime says the heap is 2444 bytes, so something is going wrong, I just don't know where. – SinisterMJ Jan 02 '17 at 14:21

1 Answers1

2

I think I solved the puzzle...

All you need to do is replacing the following like of code:

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

With the following one:

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

According to IPP documentation:

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.

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

When executing ippiResizeYUV422GetSize, value of specSize equals 11776.
When executing ippiResizeGetSize_8u, value of specSize equals 9240.
The smaller allocated size results corrupted heap.

Rotem
  • 30,366
  • 4
  • 32
  • 65