2017-01-02 2 views
0

Я пробовал следующий код, чтобы проверить, насколько быстро Intel IPP предназначен для изменения размера/преобразования изображений, но он продолжает сбой в ippsFree (pSpec) в конце, и я не могу понять, почему.Сбой Intel IPP ippsFree()

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

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

+0

Я использую новейший Intel IPP 2017.1.143 – SinisterMJ

+0

Вы попробовали освобождение сразу после выделения? И не похоже, что вы проверяете ответы об ошибках. (Отказ от ответственности: я никогда не использовал Intel IPP) – owacoder

+0

Я никогда не использовал Intel IPP. Может ли проблема заключаться в том, что вы как-то пишете вне буфера 'pSpec', который затем замечает при вызове' ippsFree'? – gurka

ответ

1

Я думаю, что я решил загадку ...

Все, что вам нужно сделать, это заменить следующий подобный код:

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

следующего текст:

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

По к документации IPP:

Описание Эта функция инициализирует структуру IppiResizeYUV422Spec для алгоритма изменения размера с использованием метода интерполяции ближайшего соседа.
Чтобы вычислить размер объекта структуры спецификации, вызовите функцию ippiResizeYUV422GetSize.

См: 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.
Меньше выделенных размеров приводит к повреждению кучи.

Смежные вопросы