代码之家  ›  专栏  ›  技术社区  ›  Yippie-Ki-Yay

C++向量问题

  •  2
  • Yippie-Ki-Yay  · 技术社区  · 15 年前

    有人知道怎么加速吗 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样式向量比 boost::numeric::ublas 即使使用自定义的基于堆栈的分配器。有人知道我怎样才能加快速度吗?

    也许是通过编写一个自定义包装器之类的东西?

    谢谢你

    3 回复  |  直到 15 年前
        1
  •  3
  •   Tomek Szpakowicz    15 年前

    BoostUBlas(通常还有BLAS)提供了对向量和矩阵代数的支持,其中维度的数量是在运行时确定的。它适用于解决某些数值问题(如有限元模拟或类似方法、优化问题、近似)。对于这些问题,它的速度相对较快,但在性能上无法与专业的竞争。 三维 矢量类库在它的地盘上。

    使用其他库。如果d3dxvector3不够,请签出,例如cgal。

        2
  •  0
  •   ravenspoint    15 年前

    我认为,如果您使用手工编码的复制构造函数等将publias::vector类继承到专门的3D vector类中,可能会获得更好的性能。类似于此代码(使用double)

    /**
    
      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); }
    
        3
  •  0
  •   ravenspoint    15 年前

    我又看了一眼,发现加快速度的最好方法是重写

       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毫秒,不管你的机器有多慢。我又问了一次:您确定您已经打开了优化并链接到了发布库吗?

    推荐文章