Как функция filter2D в OpenCV работает эффективнее, чем мой собственный код свертки?

Я пытаюсь написать свой собственный код на С++ для достижения свертки. И ядро ​​11 на 11 и неразборное. Итак, мой код такой:

for(int i = 0; i < image.rows; ++i){
    for(int j = 0; j < image.cols; ++j){
       int tmp, sum; 
       for(int m= 0; m < kernel.rows; ++m){
          for(int n = 0; n < kernel.cols; ++n){
             tmp = image[i+m-(Size_kernel-1)/2][j+n-(Size_kernel-1)/2];
             float kernel_index = kernel[m][n];
             float index_mult = (float)index_mult * kernel_index;
             sum = sum + index_mult;
          }
       }
      new_image[i][j] = sum; 
    }
 }

Мы видим, что сложность этого фрагмента кода велика. И это очень медленно, когда я запускаю программу.

Однако, когда я подключаю две матрицы к функции filter2D в OpenCV. Это занимает очень короткое время, чтобы показать результат. Может ли кто-нибудь объяснить, как filter2D в OpenCV достигает свертки? Почему существует большая разница в эффективности между OpenCV и моим собственным кодом? Спасибо!


person KathyLee    schedule 21.09.2015    source источник
comment
Вероятно, обман stackoverflow.com/questions/ 14597845/   -  person vsoftco    schedule 22.09.2015
comment
Обратите внимание, что ваш код содержит ошибки, потому что вы никогда не инициализируете sum. Что касается производительности, любая приличная реализация 2D-фильтра будет использовать SIMD, а для достаточно больших ядер реализация в частотной области будет быстрее, чем прямая реализация. И наконец: не забудьте включить оптимизацию компилятора (например, gcc -O3 ...) — это имеет большое значение для кода, подобного приведенному выше.   -  person Paul R    schedule 22.09.2015
comment
@vsoftco Итак, использует ли функция OpenCV fft для достижения двумерной свертки?   -  person KathyLee    schedule 22.09.2015
comment
@PaulR Спасибо. Я использовал оптимизацию компилятора. Он работает лучше, но все же намного медленнее, чем код OpenCV... Что такое реализация в частотной области? Можете ли вы немного объяснить это или предоставить какой-либо псевдокод или любую ссылку для этого?   -  person KathyLee    schedule 22.09.2015
comment
См. вопрос, связанный с @vsoftco выше. Я не уверен, что это будет полезно для маленького фильтра, такого как 11x11. SIMD-оптимизация, вероятно, является правильным выбором, если вы сделали все возможное для оптимизации своего скалярного кода. Опубликуйте свой фактический код на случай, если есть какие-либо оставшиеся оптимизации, которые можно использовать.   -  person Paul R    schedule 22.09.2015
comment
@PaulR Я обновил свой фактический код. посмотрю ссылку. Можете ли вы также помочь мне проверить мой код, чтобы увидеть возможную оптимизацию?   -  person KathyLee    schedule 22.09.2015
comment
Это не похоже на настоящий код — есть несколько очевидных ошибок. Пожалуйста, опубликуйте фактический код, а также включите объявления для входного и выходного изображения, ядра и локальных переменных - похоже, вы можете выполнять много неэффективной смешанной арифметики int/float, но это трудно сказать с неполным кодом.   -  person Paul R    schedule 22.09.2015
comment
Реализация вопроса довольно наивная, есть много возможностей для улучшения, в основном за счет параллелизма. SIMD уже был вызван, многопоточность также является опцией для этой дорогостоящей задачи, и Cuda или OpenCL приносят больше всего. Сам алгоритм может быть улучшен для больших ядер с помощью БПФ (как уже упоминалось), индексация заменена арифметикой указателей, используется выровненная память, оптимизированная функция свертки, построенная во время выполнения (с помощью jit), последовательные приведения (-> временное изображение с плавает), ...   -  person Youka    schedule 22.09.2015