Оптимизация c ++ матрицы / растрового класса - PullRequest
1 голос
/ 21 мая 2010

Я ищу класс 2D-матрицы (или растрового изображения), который является гибким, но также обеспечивает быстрый доступ к элементам. Содержимое Гибкий класс должен позволять вам выбирать измерения во время выполнения и выглядеть примерно так (упрощенно):

class Matrix 
{
public:   
  Matrix(int w, int h) :  
    data(new int[x*y]), width(w)  {}

 void SetElement(int x, int y, int val)  
 {  
   data[x+y*width] = val;  
 } 

 // ...
private: // symbols
  int width;  
  int* data;  
};

Более быстрое, часто предлагаемое решение с использованием шаблонов (упрощенно):

template <int W, int H>
class TMatrix {
  TMatrix() data(new int[W*H])  {}

  void SetElement(int x, int y, int val)  
  {  
    data[x+y*W] = val;  
  } 

  private:
    int* data;
};

Это быстрее, так как ширина может быть "встроена" в коде. Первое решение не делает этого. Однако это больше не очень гибко, так как вы не можете больше изменять размер во время выполнения.

Итак, мой вопрос: Есть ли возможность сказать компилятору генерировать более быстрый код (как при использовании шаблонного решения), когда размер в коде фиксирован, и генерировать гибкий код, когда его время выполнения зависит?

Я пытался добиться этого, написав "const", где это возможно. Я пробовал это с gcc и VS2005, но безуспешно. Этот вид оптимизации был бы полезен для многих других подобных случаев.

Ответы [ 3 ]

0 голосов
/ 21 мая 2010

Конечно, ваши потребности могут отличаться, но я бы пропустил автоматическую генерацию и просто пошел с простым и простым набором «фиксированных» версий. Например. Vector3, Vector4, Matrix3x3, Matrix3x4 и Matrix4x4. Я полагаю, что вы можете извлечь все из шаблонной версии, но это не будет иметь никакого значения для производительности.

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

Наконец-то, что я видел, это то, что у нас был доступ к именованным элементам, а также массив, но вы можете сделать это только с «жестко закодированными» типами. Что-то вроде:

class Vector3
{
public:
   // other stuff...

   union
   {
      struct { float x, y, z; };
      float m[3];
   };
};

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

О, даже в шаблонной версии не нужно использовать новую. Просто объявите данные как float data[W*H]; Извлечение их из кучи будет большим приростом производительности, чем «оптимизация» математики.

0 голосов
/ 21 мая 2010

Не столько полный ответ, но некоторая информация, которая может помочь (если вы об этом еще не знаете): оба OpenCV и Boost (uBLAS) имеют очень хорошие (быстрые / полные / полнофункциональные) реализации матриц. Я не смотрел в них, чтобы увидеть, как они устанавливают / получают элементы или изменяют размер после создания экземпляра.

0 голосов
/ 21 мая 2010

Я бы просто пошел с первой версией, сам.

Но, если вы действительно хотите попытаться получить лучшее из обоих миров, у вас может быть класс Matrix, который содержит указатель на полиморфный тип реализации. Для общих размеров (скажем, до 4x4) вы можете указать на создание экземпляров шаблонов, а для больших вы можете указать на реализацию, которая обрабатывает общий случай MxN.

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

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

...