[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