[GiNaC-list] new tinfo method makes is_a less efficient

Diego Conti diego.conti at unimib.it
Tue Sep 11 17:07:58 CEST 2007


Thanks for your reply.
I have made some tests, and I think I may have found a more serious 
(possibly unrelated) problem, i.e. version 1.4.0 appears to be 10 times 
slower than 1.3.8! Or am I missing something?
Here is my test program:

#include <ginac/ginac.h>
#include <ginac/version.h>
#include <iostream>
#include <time.h>

using namespace GiNaC;
using namespace std;

const unsigned TINFO_DifferentialOneForm =0x00200000U;

class DifferentialOneForm : public basic
{
    GINAC_DECLARE_REGISTERED_CLASS(DifferentialOneForm,basic);
    int id;
public:   
    DifferentialOneForm(int ID) {id=ID;}
    unsigned return_type() const {return return_types::noncommutative;}
   
    tinfo_t return_type_tinfo() const {return &tinfo_static;}    //1.4.0
    //unsigned return_type_tinfo() const {return 
TINFO_DifferentialOneForm;}    //1.3.8
   
    void do_print(const print_context & c, unsigned level) const
    {
        c.s<<"Alpha_"<<id;
    }
};


GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(DifferentialOneForm,basic,print_func<print_context>(&DifferentialOneForm::do_print));

void DifferentialOneForm::archive(archive_node & n) const {}
DifferentialOneForm::DifferentialOneForm(const archive_node & n, lst & 
sym_lst) {};
ex DifferentialOneForm::unarchive(const archive_node & n, lst & sym_lst) 
{return 0;}
int DifferentialOneForm::compare_same_type(const basic & other) const
{
    const DifferentialOneForm& o=static_cast<const 
DifferentialOneForm&>(other);
    if (id<o.id) return -1;
    else if (id>o.id) return 1;
    else return 0;
}

DifferentialOneForm::DifferentialOneForm() {id=0;}

int main()
{
    DifferentialOneForm u(1),v(2),w(3),s(4),t(5),r(6);
    symbol x,y,p;
    ex a=x*u*v+y*w*s+p*t*r;
   
    cout<<"Ginac  
"<<version_major<<"."<<version_minor<<"."<<version_micro<<endl;
    clock_t start_clock=clock();   
    for (int i=0;i<100000;i++)
        a*a*a;   
    cout<<"Product test: time elapsed: "<<(1000* 
(clock()-start_clock))/CLOCKS_PER_SEC <<"ms"<<endl;
                
}

Output:
Ginac  1.4.0
Product test: time elapsed: 4770ms

Ginac  1.3.8
Product test: time elapsed: 480ms


> Hello!
>
> First of all, it would be nice to see the actual code which proves $subject.
>   

Well, I didn't mean it literally, only that my hack that is supposed to 
speed up is_a does not work any longer. But you are probably right that 
said hack did not make much of a difference.

>
>   
>
>   
>> With the old tinfo method, I could simply redefine:
>>
>> template<> inline bool is_a<ncmul>(const basic & obj)
>> {
>>    return (obj.tinfo()&TINFO_MASK)==TINFO_ncmul;
>> }
>>     
>
> I think such a redifinition might break some GiNaC classes...
>   

But aren't all the tinfo's defined in the file tinfos.h? Then they all 
satisfy
     tinfo | TINFO_MASK = TINFO_MASK
meaning that the remaning bits are safe to use.

>   
>> where TINFO_MASK is the constant 0x001fffffU, and the classes I derived 
>> from ncmul had appropriate tinfo constants.
>>     
>
> ... but anyway, is it really faster? 
>   

Maybe only slightly so. Is there anything faster than a bitwise AND 
anyway? I don't really understand how dynamic_cast works, but I thought 
there was some overhead in the case of multiple inheritance...

>   
>> With the new method, where the tinfo_key is a pointer, the above code 
>> does not work. One obvious alternative is the following:
>>
>> struct tinfo_static_t 
>> <http://www.ginac.de/reference/structGiNaC_1_1tinfo__static__t.html>
>> {
>>    const tinfo_static_t* derives_from;   //NULL if derived from void, 
>> otherwise points to tinfo_static member in superclass 
>> <http://www.ginac.de/reference/structGiNaC_1_1tinfo__static__t.html>
>> };
>>     
>
> Ugh, now every object (even a symbol) carries information about relationship
> between _all_ GiNaC classes. Not so nice.
>
>   

Well, no...if I understand correctly,  each GiNaC class has a  member of 
type tinfo_static_t, but it's a static member. So, every class (not 
every object) carries that information, which seems alright  to me.

>> typedef const tinfo_static_t * tinfo_t;
>>
>> and then
>>
>> template <class T>
>> inline bool is_a(const basic &obj)
>> {
>>    const tinfo_static_t* tinfo=obj.tinfo();
>>    do
>>    {
>>        if (tinfo==&T::tinfo_static) return true;
>>        tinfo = tinfo->derives_from 
>> <http://www.ginac.de/reference/structGiNaC_1_1tinfo__static__t.html>;
>>    } while (tinfo!=NULL);
>>    return false;
>> }
>>
>> This appears reasonably efficient,
>>     
>
> Yes, but I doubt it will be any better than dynamic_cast. It uses very similar
> technique (see e.g. <cxxabi.h> from GNU libstdc++).
>   

Oh, I see.

Best,
Diego


More information about the GiNaC-list mailing list