Show
Ignore:
Timestamp:
09/17/08 18:14:28 (6 years ago)
Author:
robert
Message:

From Mathias Froehlich, "This is a generic optimization that does not depend on any cpu or instruction
set.

The optimization is based on the observation that matrix matrix multiplication
with a dense matrix 4x4 is 43 Operations whereas multiplication with a
transform, or scale matrix is only 4
2 operations. Which is a gain of a
*FACTOR*4* for these special cases.
The change implements these special cases, provides a unit test for these
implementation and converts uses of the expensiver dense matrix matrix
routine with the specialized versions.

Depending on the transform nodes in the scenegraph this change gives a
noticable improovement.
For example the osgforest code using the MatrixTransform? is about 20% slower
than the same codepath using the PositionAttitudeTransform? instead of the
MatrixTransform? with this patch applied.

If I remember right, the sse type optimizations did *not* provide a factor 4
improovement. Also these changes are totally independent of any cpu or
instruction set architecture. So I would prefer to have this current kind of
change instead of some hand coded and cpu dependent assembly stuff. If we
need that hand tuned stuff, these can go on top of this changes which must
provide than hand optimized additional variants for the specialized versions
to give a even better result in the end.

An other change included here is a change to rotation matrix from quaterion
code. There is a sqrt call which couold be optimized away. Since we divide in
effect by sqrt(length)*sqrt(length) which is just length ...
"

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgunittests/UnitTests_osg.cpp

    r6941 r8868  
    2020 
    2121#include <osg/Matrixd> 
     22#include <osg/Matrixf> 
     23#include <osg/Vec3d> 
    2224#include <osg/Vec3> 
    2325#include <sstream> 
     
    8587OSGUTX_AUTOREGISTER_TESTSUITE_AT(Vec3, root.osg) 
    8688 
    87 } 
     89/////////////////////////////////////////////////////////////////////////////// 
     90//  
     91//  Matrix Tests 
     92// 
     93class MatrixTestFixture 
     94{ 
     95public: 
     96 
     97    MatrixTestFixture(); 
     98 
     99    void testPreMultTranslate(const osgUtx::TestContext& ctx); 
     100    void testPostMultTranslate(const osgUtx::TestContext& ctx); 
     101    void testPreMultScale(const osgUtx::TestContext& ctx); 
     102    void testPostMultScale(const osgUtx::TestContext& ctx); 
     103    void testPreMultRotate(const osgUtx::TestContext& ctx); 
     104    void testPostMultRotate(const osgUtx::TestContext& ctx); 
     105 
     106private: 
     107 
     108    // Some convenience variables for use in the tests 
     109    Matrixd _md; 
     110    Matrixf _mf; 
     111    Vec3d _v3d; 
     112    Vec3 _v3; 
     113    Quat _q1; 
     114    Quat _q2; 
     115    Quat _q3; 
     116    Quat _q4; 
     117 
     118}; 
     119 
     120MatrixTestFixture::MatrixTestFixture(): 
     121    _md(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 
     122    _mf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 
     123    _v3d(1, 2, 3), 
     124    _v3(1, 2, 3), 
     125    _q1(1, 0, 0, 0), 
     126    _q2(0, 1, 0, 0), 
     127    _q3(0, 0, 1, 0), 
     128    _q4(0, 0, 0, 1) 
     129{ 
     130} 
     131 
     132void MatrixTestFixture::testPreMultTranslate(const osgUtx::TestContext&) 
     133{ 
     134    osg::Matrixd tdo; 
     135    osg::Matrixd tdn; 
     136    osg::Matrixf tfo; 
     137    osg::Matrixf tfn; 
     138 
     139    tdo = _md; 
     140    tdn = _md; 
     141    tdo.preMult(osg::Matrixd::translate(_v3d)); 
     142    tdn.preMultTranslate(_v3d); 
     143    OSGUTX_TEST_F( tdo == tdn ) 
     144 
     145    tdo = _md; 
     146    tdn = _md; 
     147    tdo.preMult(osg::Matrixd::translate(_v3)); 
     148    tdn.preMultTranslate(_v3); 
     149    OSGUTX_TEST_F( tdo == tdn ) 
     150 
     151    tfo = _mf; 
     152    tfn = _mf; 
     153    tfo.preMult(osg::Matrixf::translate(_v3d)); 
     154    tfn.preMultTranslate(_v3d); 
     155    OSGUTX_TEST_F( tfo == tfn ) 
     156 
     157    tfo = _mf; 
     158    tfn = _mf; 
     159    tfo.preMult(osg::Matrixf::translate(_v3)); 
     160    tfn.preMultTranslate(_v3); 
     161    OSGUTX_TEST_F( tfo == tfn ) 
     162} 
     163 
     164void MatrixTestFixture::testPostMultTranslate(const osgUtx::TestContext&) 
     165{ 
     166    osg::Matrixd tdo; 
     167    osg::Matrixd tdn; 
     168    osg::Matrixf tfo; 
     169    osg::Matrixf tfn; 
     170 
     171    tdo = _md; 
     172    tdn = _md; 
     173    tdo.postMult(osg::Matrixd::translate(_v3d)); 
     174    tdn.postMultTranslate(_v3d); 
     175    OSGUTX_TEST_F( tdo == tdn ) 
     176 
     177    tdo = _md; 
     178    tdn = _md; 
     179    tdo.postMult(osg::Matrixd::translate(_v3)); 
     180    tdn.postMultTranslate(_v3); 
     181    OSGUTX_TEST_F( tdo == tdn ) 
     182 
     183    tfo = _mf; 
     184    tfn = _mf; 
     185    tfo.postMult(osg::Matrixf::translate(_v3d)); 
     186    tfn.postMultTranslate(_v3d); 
     187    OSGUTX_TEST_F( tfo == tfn ) 
     188 
     189    tfo = _mf; 
     190    tfn = _mf; 
     191    tfo.postMult(osg::Matrixf::translate(_v3)); 
     192    tfn.postMultTranslate(_v3); 
     193    OSGUTX_TEST_F( tfo == tfn ) 
     194} 
     195 
     196void MatrixTestFixture::testPreMultScale(const osgUtx::TestContext&) 
     197{ 
     198    osg::Matrixd tdo; 
     199    osg::Matrixd tdn; 
     200    osg::Matrixf tfo; 
     201    osg::Matrixf tfn; 
     202 
     203    tdo = _md; 
     204    tdn = _md; 
     205    tdo.preMult(osg::Matrixd::scale(_v3d)); 
     206    tdn.preMultScale(_v3d); 
     207    OSGUTX_TEST_F( tdo == tdn ) 
     208 
     209    tdo = _md; 
     210    tdn = _md; 
     211    tdo.preMult(osg::Matrixd::scale(_v3)); 
     212    tdn.preMultScale(_v3); 
     213    OSGUTX_TEST_F( tdo == tdn ) 
     214 
     215    tfo = _mf; 
     216    tfn = _mf; 
     217    tfo.preMult(osg::Matrixf::scale(_v3d)); 
     218    tfn.preMultScale(_v3d); 
     219    OSGUTX_TEST_F( tfo == tfn ) 
     220 
     221    tfo = _mf; 
     222    tfn = _mf; 
     223    tfo.preMult(osg::Matrixf::scale(_v3)); 
     224    tfn.preMultScale(_v3); 
     225    OSGUTX_TEST_F( tfo == tfn ) 
     226} 
     227 
     228void MatrixTestFixture::testPostMultScale(const osgUtx::TestContext&) 
     229{ 
     230    osg::Matrixd tdo; 
     231    osg::Matrixd tdn; 
     232    osg::Matrixf tfo; 
     233    osg::Matrixf tfn; 
     234 
     235    tdo = _md; 
     236    tdn = _md; 
     237    tdo.postMult(osg::Matrixd::scale(_v3d)); 
     238    tdn.postMultScale(_v3d); 
     239    OSGUTX_TEST_F( tdo == tdn ) 
     240 
     241    tdo = _md; 
     242    tdn = _md; 
     243    tdo.postMult(osg::Matrixd::scale(_v3)); 
     244    tdn.postMultScale(_v3); 
     245    OSGUTX_TEST_F( tdo == tdn ) 
     246 
     247    tfo = _mf; 
     248    tfn = _mf; 
     249    tfo.postMult(osg::Matrixf::scale(_v3d)); 
     250    tfn.postMultScale(_v3d); 
     251    OSGUTX_TEST_F( tfo == tfn ) 
     252 
     253    tfo = _mf; 
     254    tfn = _mf; 
     255    tfo.postMult(osg::Matrixf::scale(_v3)); 
     256    tfn.postMultScale(_v3); 
     257    OSGUTX_TEST_F( tfo == tfn ) 
     258} 
     259 
     260void MatrixTestFixture::testPreMultRotate(const osgUtx::TestContext&) 
     261{ 
     262    osg::Matrixd tdo; 
     263    osg::Matrixd tdn; 
     264    osg::Matrixf tfo; 
     265    osg::Matrixf tfn; 
     266 
     267    tdo = _md; 
     268    tdn = _md; 
     269    tdo.preMult(osg::Matrixd::rotate(_q1)); 
     270    tdn.preMultRotate(_q1); 
     271    OSGUTX_TEST_F( tdo == tdn ) 
     272 
     273    tdo = _md; 
     274    tdn = _md; 
     275    tdo.preMult(osg::Matrixd::rotate(_q2)); 
     276    tdn.preMultRotate(_q2); 
     277    OSGUTX_TEST_F( tdo == tdn ) 
     278 
     279    tdo = _md; 
     280    tdn = _md; 
     281    tdo.preMult(osg::Matrixd::rotate(_q3)); 
     282    tdn.preMultRotate(_q3); 
     283    OSGUTX_TEST_F( tdo == tdn ) 
     284 
     285    tdo = _md; 
     286    tdn = _md; 
     287    tdo.preMult(osg::Matrixd::rotate(_q4)); 
     288    tdn.preMultRotate(_q4); 
     289    OSGUTX_TEST_F( tdo == tdn ) 
     290 
     291    tfo = _mf; 
     292    tfn = _mf; 
     293    tfo.preMult(osg::Matrixf::rotate(_q1)); 
     294    tfn.preMultRotate(_q1); 
     295    OSGUTX_TEST_F( tfo == tfn ) 
     296 
     297    tfo = _mf; 
     298    tfn = _mf; 
     299    tfo.preMult(osg::Matrixf::rotate(_q2)); 
     300    tfn.preMultRotate(_q2); 
     301    OSGUTX_TEST_F( tfo == tfn ) 
     302 
     303    tfo = _mf; 
     304    tfn = _mf; 
     305    tfo.preMult(osg::Matrixf::rotate(_q3)); 
     306    tfn.preMultRotate(_q3); 
     307    OSGUTX_TEST_F( tfo == tfn ) 
     308 
     309    tfo = _mf; 
     310    tfn = _mf; 
     311    tfo.preMult(osg::Matrixf::rotate(_q4)); 
     312    tfn.preMultRotate(_q4); 
     313    OSGUTX_TEST_F( tfo == tfn ) 
     314} 
     315 
     316void MatrixTestFixture::testPostMultRotate(const osgUtx::TestContext&) 
     317{ 
     318    osg::Matrixd tdo; 
     319    osg::Matrixd tdn; 
     320    osg::Matrixf tfo; 
     321    osg::Matrixf tfn; 
     322 
     323    tdo = _md; 
     324    tdn = _md; 
     325    tdo.postMult(osg::Matrixd::rotate(_q1)); 
     326    tdn.postMultRotate(_q1); 
     327    OSGUTX_TEST_F( tdo == tdn ) 
     328 
     329    tdo = _md; 
     330    tdn = _md; 
     331    tdo.postMult(osg::Matrixd::rotate(_q2)); 
     332    tdn.postMultRotate(_q2); 
     333    OSGUTX_TEST_F( tdo == tdn ) 
     334 
     335    tdo = _md; 
     336    tdn = _md; 
     337    tdo.postMult(osg::Matrixd::rotate(_q3)); 
     338    tdn.postMultRotate(_q3); 
     339    OSGUTX_TEST_F( tdo == tdn ) 
     340 
     341    tdo = _md; 
     342    tdn = _md; 
     343    tdo.postMult(osg::Matrixd::rotate(_q4)); 
     344    tdn.postMultRotate(_q4); 
     345    OSGUTX_TEST_F( tdo == tdn ) 
     346 
     347    tfo = _mf; 
     348    tfn = _mf; 
     349    tfo.postMult(osg::Matrixf::rotate(_q1)); 
     350    tfn.postMultRotate(_q1); 
     351    OSGUTX_TEST_F( tfo == tfn ) 
     352 
     353    tfo = _mf; 
     354    tfn = _mf; 
     355    tfo.postMult(osg::Matrixf::rotate(_q2)); 
     356    tfn.postMultRotate(_q2); 
     357    OSGUTX_TEST_F( tfo == tfn ) 
     358 
     359    tfo = _mf; 
     360    tfn = _mf; 
     361    tfo.postMult(osg::Matrixf::rotate(_q3)); 
     362    tfn.postMultRotate(_q3); 
     363    OSGUTX_TEST_F( tfo == tfn ) 
     364 
     365    tfo = _mf; 
     366    tfn = _mf; 
     367    tfo.postMult(osg::Matrixf::rotate(_q4)); 
     368    tfn.postMultRotate(_q4); 
     369    OSGUTX_TEST_F( tfo == tfn ) 
     370} 
     371 
     372OSGUTX_BEGIN_TESTSUITE(Matrix) 
     373    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPreMultTranslate) 
     374    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPostMultTranslate) 
     375    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPreMultScale) 
     376    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPostMultScale) 
     377    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPreMultRotate) 
     378    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPostMultRotate) 
     379OSGUTX_END_TESTSUITE 
     380 
     381OSGUTX_AUTOREGISTER_TESTSUITE_AT(Matrix, root.osg) 
     382 
     383 
     384}