Boost logo

Boost :

From: Andy Little (andy_at_[hidden])
Date: 2006-08-21 01:20:15


"Matthias Troyer" <troyer_at_[hidden]> wrote in message
news:B1F6950B-29D5-4F04-BDC0-7D6E7A56038F_at_itp.phys.ethz.ch...
>
> On Aug 20, 2006, at 4:19 PM, Andy Little wrote:

>> T temp = 0.5;
>> temp *= a;
>> temp *= t;
>> temp *= t;
>> s += temp;
>
>
> This is completely wrong. a is a vector and you thus cannot multiply
> it to the scalar 0.5

OK. OTOH it prompted me to start writing another performance test. Its not
finished yet, but in contrast to what I said it appears that Quan types perform
quite well in comparison to inbuilts in this case ( based on two_param-branch in
quan CVS which has had vectors improved relative to quan-0_1_0). As always one
should be very careful with these tests!. In this case, maybe, because the Quan
expression is evaluated first, it grabs the better registers. Anyway here is the
source so far. I need to add some timing, but the assembly output from VC8
suggests that Quan does quite well in this particular case. It may mean I could
write the double expression better too of course

#include <quan/three_d/out/vect.hpp>
#include <quan/out/velocity.hpp>
#include <quan/out/acceleration.hpp>
#include <quan/out/time.hpp>
#include <quan/out/length.hpp>
#include <quan/fixed_quantity/io/input.hpp>
#include <fstream>
/*
    vector of double v vector of quantities
*/

int main()
{
    typedef quan::acceleration::m_per_s2 accel;
    typedef quan::velocity::m_per_s velocity;
    typedef quan::length::m length;

    using quan::three_d::vect;

    typedef vect<accel> accel_vect;
    typedef vect<velocity> velocity_vect;
    typedef vect<length> distance_vect;

    accel_vect a(accel(333.),accel(444.),accel(555.));
    velocity_vect u(velocity(666.),velocity(777.), velocity(888.));
    quan::time::s t(.5);
    // nuke the optimiser
    {
        std::ofstream qos("quantity.txt");
        qos << a.x << '\n' << a.y << '\n' << a.z <<'\n';
        qos << u.x << '\n' << u.y << '\n' << u.z <<'\n';
        qos << t <<'\n';
    }
    {
        std::ifstream qis("quantity.txt");
        qis >> a.x >> a.y >> a.z >> u.x >>u.y >> u.z >> t;
    }

    distance_vect s = u * t;
    distance_vect temp = a * t * t;
    temp *=0.5;
    s += temp;

    std::cout << "quantity vect result= " << s <<'\n';

    // double version
    typedef vect<double> vectd;

    vectd a1(333.,444.,555.), u1(666.,777.,888.);
    double t1 = 0.5;
    // nuke the optimiser
    {
        std::ofstream os("double.txt");
        os << a1.x << '\n' << a1.y << '\n' << a1.z <<'\n';
        os << u1.x << '\n' << u1.y << '\n' << u1.z <<'\n';
        os << t1 <<'\n';
    }
    {
        std::ifstream is("double.txt");
        is >> a1.x >> a1.y >> a1.z >> u1.x >>u1.y >> u1.z >> t1;
    }

     vectd s1 = u1;
     s1 *= t1;
     vectd temp1 = a1;
     temp1 *= 0.5;
     temp1 *= t1;
     temp1 *=t1;
     s1 += temp1;

    std::cout << "double vect result= " << s1 <<'\n';
}

chopped output of respective calcs in VC* with a lot of optimsiation
///////////////////////
quan calc

; 40 : distance_vect s = u * t;

 fld QWORD PTR _u$[esp+536]
 fld QWORD PTR _t$[esp+520]
 add esp, 4
 fmul ST(1), ST(0)

; 41 : distance_vect temp = a * t * t;
; 42 : temp *=0.5;
; 43 : s += temp;
; 44 :
; 45 : std::cout << "quantity vect result= " << s <<'\n';

 push OFFSET $SG-215
 fld QWORD PTR _u$[esp+528]
 push OFFSET ?cout_at_std@@3V?$basic_ostream_at_DU?$char_traits_at_D@std@@@1_at_A ;
std::cout
 fmul ST(0), ST(1)
 fld QWORD PTR _u$[esp+524]
 fmul ST(0), ST(2)
 fld QWORD PTR _a$[esp+540]
 fmul ST(0), ST(3)
 fld QWORD PTR _a$[esp+532]
 fmul ST(0), ST(4)
 fld QWORD PTR _a$[esp+524]
 fmul ST(0), ST(5)
 fxch ST(2)
 fmul ST(0), ST(5)
 fxch ST(1)
 fmul ST(0), ST(5)
 fxch ST(2)
 fmulp ST(5), ST(0)
 fld QWORD PTR __real_at_3fe0000000000000
 fmul ST(5), ST(0)
 fmul ST(2), ST(0)
 fmulp ST(1), ST(0)
 fxch ST(2)
 faddp ST(4), ST(0)
 fxch ST(3)
 fstp QWORD PTR _s$[esp+524]
 fxch ST(2)
 faddp ST(1), ST(0)
 fstp QWORD PTR _s$[esp+532]
 faddp ST(1), ST(0)
 fstp QWORD PTR _s$[esp+540]
 call ??$?6U?$char_traits_at_D@std@@@std@@YAAAV?$basic_ostream@

// double calc

; 65 : vectd s1 = u1;

 fld QWORD PTR _u1$[esp+520]
 fst QWORD PTR _s1$[esp+520]
 add esp, 4
 fld QWORD PTR _u1$[esp+524]

; 66 : s1 *= t1;
; 67 : vectd temp1 = a1;
; 68 : temp1 *= 0.5;
; 69 : temp1 *= t1;
; 70 : temp1 *=t1;
; 71 : s1 += temp1;
; 72 :
; 73 : std::cout << "double vect result= " << s1 <<'\n';

 push OFFSET $SG-218
 fld QWORD PTR _u1$[esp+536]
 push OFFSET ?cout_at_std@@3V?$basic_ostream_at_DU?$char_traits_at_D@std@@@1_at_A ;
std::cout
 fld QWORD PTR _t1$[esp+524]
 fmul ST(3), ST(0)
 fmul ST(2), ST(0)
 fmul ST(1), ST(0)
 fld QWORD PTR _a1$[esp+524]
 fst QWORD PTR _temp1$[esp+524]
 fld QWORD PTR _a1$[esp+532]
 fld QWORD PTR _a1$[esp+540]
 fld QWORD PTR __real_at_3fe0000000000000
 fmul ST(3), ST(0)
 fmul ST(2), ST(0)
 fmulp ST(1), ST(0)
 fxch ST(2)
 fmul ST(0), ST(3)
 fxch ST(1)
 fmul ST(0), ST(3)
 fxch ST(2)
 fmul ST(0), ST(3)
 fxch ST(1)
 fmul ST(0), ST(3)
 fxch ST(2)
 fmul ST(0), ST(3)
 fxch ST(1)
 fmulp ST(3), ST(0)
 fxch ST(1)
 faddp ST(5), ST(0)
 fxch ST(4)
 fstp QWORD PTR _s1$[esp+524]
 fxch ST(3)
 faddp ST(2), ST(0)
 fxch ST(1)
 fstp QWORD PTR _s1$[esp+532]
 faddp ST(1), ST(0)
 fstp QWORD PTR _s1$[esp+540]
 call
??$?6U?$char_traits_at_D@std@@@std@@YAAAV?$basic_ostream_at_DU?$char_traits_at_D@std@@@0_at_AAV10@PBD_at_Z
; std::operator<<<std::char_traits<char> >
 mov esi, eax

///////////////////////

>> In fact you can do in place addition of quantities of course, but not
>> multiplication, or at least not without low level manipulations.
>>
>> It sounds like I am arguing against my own library. I'm not, but I
>> am pointing
>> out that there are different considerations when using quantities
>> and you may
>> not ( in fact probably wont) get as good a performance as from
>> using inbuilt
>> floats. Overall Quan is much more fun to use than floats though,
>> and I have
>> enjoyed using it so far where possible..
>
> In fact it seems to me that you are much better off using a nice
> linear algebra library that makes use of expression templates.

To be honest you have lost me here.
Are you now saying it would be better for me to ditch Quan and start writing a
linear algebra library for floats that uses E.T?

There are a few of those around already. OTOH If an E.T library is any good then
it should be possible to get Quan to work with it.
However in the case of existing linear algebra libraries, they are all
(including AFAICS MTL2) just set up for floats and possibly numeric UDT's.

>> FWIW I do see the difference between using quantities and floats as
>> very
>> coarsely equivalent to the difference between using an assembly
>> language and
>> (say) C. When using quantities you are effectively using a higher
>> level
>> language than standard C ++ using floats.
>
> I disagree since the units part is optimized away at compile time and
> you should be left just with pure floating point operations at the
> end of the day.

That is a different issue . Sure it is possible for the compiler to optimise the
details of a higher level language and I am doing what I can to make sure it
does so, but that doesnt change the fact that it's a higher level language.

And as a user I have found Quan is a lot of fun to use. The issue is always
going to be a lack of supporting libraries. For me though it is a good learning
process to try to understand quaternions and more about linear algebra in
general by trying to write some supporting librraies for quan.

regards
Andy Little


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk