Eigen: ускорить сложную матричную инверсию - PullRequest
0 голосов
/ 15 октября 2018

Я занимаюсь разработкой встроенного программного обеспечения на Zynq MPSOC Cortex-A53 (Armv7 / Armv8) для обработки изображений, и мне нужна помощь для разработки конкретного алгоритма.

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

Очевидно, что наиболее значимым ограничением является ограничение по времени : мы используем для разработки наших алгоритмов с ARM NEON SIMD дляБыстрее.

Для этого я сейчас тестирую библиотеку Eigen v3.3.5 .Я написал код для инверсии и для матрицы 24x24 (тип complex double, функция Eigen :: MatrixXcd :: inverse () ): я получил среднюю продолжительность 10,5 мс.

Мой код:

#include <complex>
#include <cmath>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <Eigen/Dense>

static const unsigned int N_ROWS = 24;
static const unsigned int N_COLS = 24;
static const unsigned int NB_test = 20U;

// MAIN
int main(int argc, char** argv)
{

  TimeTools TheTimer;
  Eigen::MatrixXcd Matrix_cpx(N_ROWS, N_COLS);
  Eigen::MatrixXcd Matrix_cpx_inv;

  F32 ChronoResult[NB_test] = {0.0};
  for(unsigned int TestIdx = 0U; TestIdx < NB_test; TestIdx ++)
  {
    // Get random matrix
    Matrix_cpx = Eigen::MatrixXcd::Random(N_ROWS, N_COLS);

    TheTimer.StartChrono();
    // Inverse matrix
    Matrix_cpx_inv = Matrix_cpx.inverse();
    TheTimer.StopChrono();

    // Save chrono
    ChronoResult[TestIdx] = TheTimer.GetChronoValue();
  }

  std::cout << "\nM matrix is:\n" << Matrix_cpx << std::endl;
  std::cout << "\nM_inv matrix is:\n" << Matrix_cpx_inv << std::endl;
  F64 SumChrono = 0.0;
  for(unsigned int TestIdx = 0U; TestIdx < NB_test; TestIdx ++)
  {
    std::cout << "\nMatrix_Inversion duration[" << TestIdx << "] = "<< ChronoResult[TestIdx] << " ms" << std::endl;
    SumChrono += ChronoResult[TestIdx];
  }
  std::cout << "\nMatrix_Inversion average duration = "<< (SumChrono / NB_test) << " ms" << std::endl;

  return 0;
}

Примечание: за TimeTools используется gettimeofday () .

Моя цель - ускоритьдо этой матрицы инверсии.Следовательно, мне нужна ваша помощь: как сделать это быстрее?

Я знаю, что Eigen может использовать ARM NEON SIMD для оптимизации определенных функций, но я не уверен, что Eigen используетэто для обращения матрицы.Как это узнать?

Нужно ли устанавливать опцию (= определить), чтобы включить NEON?Или другие варианты, которые могут оптимизировать собственный код?

Примечания:

  • Компилятор arm-linux-gnueabi-g ++ (32бит)
  • Опции компилятора: -mcpu = cortex-a53 -mfloat-abi = softfp -mfpu = neon-vfpv4
  • Процессор работает на частоте 1,2 ГГц.

Заранее благодарю.

С уважением,

Лоран.

ОБНОВЛЕНИЕ

Я забыл флаг оптимизации ..С опцией -O3 компилятор я получил 0,82 мс длительность.

Любые идеи по оптимизации больше будут приветствоваться!

UPDATE2

С опцией ffast-math сборки я получил 0,4 мс длительность.

Я продолжаю искать более быструю реализацию!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...