Вопрос о векторах C ++ - PullRequest
2 голосов
/ 15 июля 2010

Кто-нибудь знает, как ускорить boost::numeric::ublas::vector?

Я использую typedef ublas::vector<float, ublas::bounded_array<float, 3> > MYVECTOR3 и сравниваю его скорость с D3DXVECTOR3 для простых операций.

Тестовый видследующим образом:

#include <d3dx9.h>
#pragma comment(lib, "d3dx9.lib")

static const size_t kRuns = static_cast<size_t>(10e6);

TEST(Performance, CStyleVectors) {

   D3DXVECTOR3 a(1.0f, 2.0f, 3.0f);
   D3DXVECTOR3 b(2.0f, 3.0f, 1.0f);
   D3DXVECTOR3 c(6.0f, 4.0f, 5.0f);

   for (size_t i = 0; i < kRuns; ++i) {
      c = c + (a + b) * 0.5f;
   }
}

#include <boost/numeric/ublas/vector.hpp>

TEST(Performance, CppStyleVectors) {

   typedef boost::numeric::ublas::vector<float, 
      boost::numeric::ublas::bounded_array<float, 3> > MYVECTOR3;

   MYVECTOR3 a(3), b(3), c(3);
   a[0] = 1.0f, a[1] = 2.0f, a[2] = 3.0f;
   b[0] = 2.0f, b[1] = 3.0f, b[2] = 1.0f;
   c[0] = 6.0f, c[1] = 4.0f, c[2] = 5.0f;

   for (size_t i = 0; i < kRuns; ++i) {
      noalias(c) = c + (a + b) * 0.5f;
   }
}

И результаты следующие:

[----------] 2 tests from Performance
[ RUN      ] Performance.CStyleVectors
[       OK ] Performance.CStyleVectors (484 ms)
[ RUN      ] Performance.CppStyleVectors
[       OK ] Performance.CppStyleVectors (9406 ms)
[----------] 2 tests from Performance (9890 ms total)

Как видите, простой вектор в стиле CВ 20 раз быстрее, чем у boost::numeric::ublas, даже при использовании пользовательского распределителя на основе стека.У кого-нибудь есть идеи о том, как я могу ускорить это?

Может быть, написав специальную оболочку или что-то в этом роде?

Спасибо

Ответы [ 3 ]

3 голосов
/ 15 июля 2010

Повышение uBLAS (и BLAS в целом) обеспечивает поддержку векторной и матричной алгебры, где число измерений определяется во время выполнения. Он подходит для решения определенной численной задачи (например, моделирование с помощью метода конечных элементов или аналогичного метода, задачи оптимизации, аппроксимация). Для решения этих проблем это относительно быстро, но не может конкурировать по производительности со специализированной 3d векторной библиотекой классов на своей территории.

Используйте другую библиотеку. Если D3DXVECTOR3 недостаточно, проверьте, например, CGAL. ​​

0 голосов
/ 18 июля 2010

Я еще раз взглянул на это и понял, что лучший способ ускорить его - переписать

   for (size_t i = 0; i < kRuns; ++i) {
      c = c + (a + b) * 0.5f;
   }

в

c = c + kRuns * ( a + b ) * 0.5f

, что совсем не требует времени.

Когда я передаю код с использованием простых массивов, мой оптимизирующий компилятор, очевидно, делает это для «цикла», который выполняется миллион раз за слишком короткое время для измерения.

   float a[3], b[3], c[3];
   a[0] = 1.0f, a[1] = 2.0f, a[2] = 3.0f;
   b[0] = 2.0f, b[1] = 3.0f, b[2] = 1.0f;
   c[0] = 6.0f, c[1] = 4.0f, c[2] = 5.0f;

   for (size_t i = 0; i < KRUNS; ++i) {
       c[0] = c[0] + ( a[0] + b[0] ) * 0.5;
       c[1] = c[1] + ( a[1] + b[1] ) * 0.5;
       c[2] = c[2] + ( a[2] + b[2] ) * 0.5;
   }

Не твой?

Использование библиотеки ublas не позволяет оптимизатору делать свое дело. Запуск этого кода

   #define KRUNS 1000000
   typedef boost::numeric::ublas::vector<float, 
      boost::numeric::ublas::bounded_array<float, 3> > MYVECTOR3;

   MYVECTOR3 a(3), b(3), c(3);
   a[0] = 1.0f, a[1] = 2.0f, a[2] = 3.0f;
   b[0] = 2.0f, b[1] = 3.0f, b[2] = 1.0f;
   c[0] = 6.0f, c[1] = 4.0f, c[2] = 5.0f;

   for (size_t i = 0; i < KRUNS; ++i) {
      noalias(c) = c + (a + b) * 0.5f;
   }

занимает 63 миллисекунды. Я не могу представить, почему для вас это займет 9400 миллисекунд, независимо от того, насколько медленна ваша машина. Я снова спрашиваю: вы уверены, что включили оптимизацию и делаете ссылки на библиотеки релизов?

0 голосов
/ 15 июля 2010

Я думаю, что возможно, вы получите лучшую производительность, если унаследуете от класса ublas :: vector в специализированный 3D векторный класс с конструктором копирования с ручным кодированием и т. Д. Что-то вроде этого кода (который использует удваивается) *

/**

  A 3D vector

*/
class c3d : public boost::numeric::ublas::bounded_vector<double, 3>
{
    typedef boost::numeric::ublas::bounded_vector<double, 3> Base_vector;
public:

    //  ctors
    c3d () : Base_vector()
    {}
    c3d (double x, double y, double z) : Base_vector()
    { Base_vector::iterator p = begin(); *p++=x; *p++=y; *p++=z;}
    template <class R> c3d (const boost::numeric::ublas::vector_expression<R>& r) : Base_vector(r)
    {}
    template <class R> void operator=(const boost::numeric::ublas::vector_expression<R>& r)
    { Base_vector::operator=(r); }
    template <class R> void operator=(const Base_vector& r)
    { Base_vector::operator=(r); }
...