2016-06-03 6 views
1

Я обрабатываю UHD (2160 x 3840) изображения. Одна из обработок, которую я выполняю, состоит в обработке фильтрации Собеля по оси X и Y, тогда мне нужно умножить каждую выходную матрицу на ее транспонирование, а затем обработать градиентное изображение как квадратный корень из суммы градиента.интерфейс Контейнеры для контейнеров OpenCV с blas для умножения матрицы

So: S = sqrt (S_x * S_x^t + S_y * S_y^t).

Из-за размера изображения OpenCV занимает до двадцати секунд для обработки без многопоточности и десяти с многопоточным.

Я знаю, что OpenCV вызывает OpenCL, чтобы ускорить операции фильтрации, поэтому я думаю, что это может занять много времени, чтобы попытаться получить производительность с этапа фильтрации.

Для матричного умножения я испытываю нестабильность от реализации ядра OpenCV с открытым ядром.

Так что я хотел бы попробовать использовать OpenBLAS insted.

Мои вопросы:

1.)

Я написал следующий код, но я сталкиваюсь некоторые проблемы для объектов, Матем интерфейсного OpenCV в:

template<class _Ty> 
void mm(cv::Mat& A,cv::Mat& B,cv::Mat& C) 
{ 
    static_assert(true,"support matrix_multiply is only defined for floating precision numbers."); 
} 

template<> 
inline void mm<float>(cv::Mat& A,cv::Mat& B,cv::Mat& C) 
{ 
    const int M = A.rows; 
    const int N = B.cols; 
    const int K = A.cols; 

    cblas_sgemm(CblasRowMajor ,// 1 
       CblasNoTrans, // 2 TRANSA 
       CblasNoTrans, // 3 TRANSB 
       M,  // 4 M 
       N,  // 5 N 
       K,  // 6 K 
       1.,   // 7 ALPHA 
       A.ptr<float>(),//8 A 
       A.rows,  //9 LDA 
       B.ptr<float>(),//10 B 
       B.rows,  //11 LDB 
       0.,   //12 BETA 
       C.ptr<float>(),//13 C 
       C.rows);  //14 LDC 

} 

template<> 
inline void mm<double>(cv::Mat& A,cv::Mat& B,cv::Mat& C) 
{ 
    cblas_dgemm(CblasRowMajor,CblasNoTrans,CblasNoTrans,A.rows,B.cols,A.cols,1.,A.ptr<double>(),A.rows,B.ptr<double>(),B.cols,0.,C.ptr<double>(),C.rows); 
} 
    void matrix_multiply(cv::InputArray _src1, cv::InputArray _src2, cv::OutputArray _dst) 
    { 

     CV_DbgAssert( (_src1.isMat() || _src1.isUMat()) && (_src1.kind() == _src2.kind()) && 
         (_src1.depth() == _src2.depth()) && (_src1.depth() == CV_32F) && (_src1.depth() == _src1.type()) && 
         (_src1.rows() == _src2.cols()) 
         ); 


     cv::Mat src1 = _src1.getMat(); 
     cv::Mat src2 = _src2.getMat(); 
     cv::Mat dst; 

     bool cpy(false); 

     if(_dst.rows() == _src1.rows() && _dst.cols() == _src2.cols() && _dst.type() == _src1.type()) 
      dst = _dst.getMat(); 
     else 
     { 
      dst = cv::Mat::zeros(src1.rows,src2.cols,src1.type()); 
      cpy = true; 
     } 

     if(cpy) 
      dst.copyTo(_dst); 
    } 

Я пытался организовать ДАННЫЕ, как указано здесь: http://www.netlib.org/lapack/explore-html/db/dc9/group__single__blas__level3.html#gafe51bacb54592ff5de056acabd83c260

без успешных действий. Это мой главный вопрос

2.) Я думал, чтобы попытаться ускорить немного моей реализации, чтобы применить разделяй и властвуй подход иллюстрируется здесь:

https://en.wikipedia.org/wiki/Matrix_multiplication_algorithm

Но только четыре подматрицы. Пробовал ли какой-либо подобный подход или получил лучший способ повысить производительность при умножении матрицы (без использования GPU)?

Заранее благодарю за любую помощь.

ответ

1

Я нашел решение вопроса 1). Я основывал свою первую реализацию на документации библиотеки BLAS. BLAS написан на языке Fortran, на этом языке индекс начинается с 1, а не 0, как на C или C++. Другое дело, что многие библиотеки, написанные на языке Fortran, организуют свою память в порядке столбцов (например, BLAS, LAPACK), а не в большинстве библиотек C или C++ (например, OpenCV) организуют память в порядке строк.

После приема этих двух свойств в счете я изменил мой код:

template<class _Ty> 
void mm(cv::Mat& A,cv::Mat& B,cv::Mat& C) 
{ 
    static_assert(true,"The function gemm is only defined for floating precision numbers."); 
} 

template<> 
void mm<float>(cv::Mat& A,cv::Mat& B,cv::Mat& C) 
{ 
    const int M = A.cols+1; 
    const int N = B.rows; 
    const int K = A.cols; 

    cblas_sgemm(CblasRowMajor ,// 1 
       CblasNoTrans, // 2 TRANSA 
       CblasNoTrans, // 3 TRANSB 
       M,  // 4 M 
       N,  // 5 N 
       K,  // 6 K 
       1.,   // 7 ALPHA 
       A.ptr<float>(),//8 A 
       A.step1(),  //9 LDA 
       B.ptr<float>(),//10 B 
       B.step1(),  //11 LDB 
       0.,   //12 BETA 
       C.ptr<float>(),//13 C 
       C.step1());  //14 LDC 
} 

template<> 
void mm<double>(cv::Mat& A,cv::Mat& B,cv::Mat& C) 
{ 
    const int M = A.cols+1; 
    const int N = B.rows; 
    const int K = A.cols; 

    cblas_dgemm(CblasRowMajor ,// 1 
       CblasNoTrans, // 2 TRANSA 
       CblasNoTrans, // 3 TRANSB 
       M,  // 4 M 
       N,  // 5 N 
       K,  // 6 K 
       1.,   // 7 ALPHA 
       A.ptr<double>(),//8 A 
       A.step1(),  //9 LDA 
       B.ptr<double>(),//10 B 
       B.step1(),  //11 LDB 
       0.,   //12 BETA 
       C.ptr<double>(),//13 C 
       C.step1());  //14 LDC 
} 

И каждая вещь работает хорошо. Без дополнительного подхода к многопоточности или разделения и захвата я смог сократить время обработки одного шага моего кода от 150 мс до 500 мс. Так что я все исправлю для себя :).