Archived

This topic is now archived and is closed to further replies.

BSXrider

"private:" data members SLOOOW

Recommended Posts

BSXrider    122
Benchmarking: 1) code as below in source: 17.3 seconds 2) as below but "void" setx member function with no return: 17.5 seconds (!) 3) as below but passing i by value instead of reference in setx: 19.0 seconds 4) using "public:" data members and "v1.x" instead of set/get routines: 3.8 seconds. Can things be speeded up without the cretinous sin of public data members? edit: 5) solved using "inlines". 3.9 seconds. - seb
    
float Vect::getx() const
{
	return xcoord;
}

Vect &Vect::setx(const float & value)
{
	xcoord = value;

	return *this;
}

int main()
{
	int i=0;
	float x=0;

	Vect v1(0,0,0);
	
	long time0=GetTickCount();
	
	for(;i<1000000000;++i)
	{
		v1.setx(i);
		x=v1.getx();
	}

	long time1=GetTickCount();
	
	cout << time1-time0;

	return 0;
}
    
Edited by - bsxrider on January 29, 2002 7:53:53 AM

Share this post


Link to post
Share on other sites
Prosper/LOADED    100
You should put your accessor member functions in the header of your class and declare them as 'inline'.

Here's a better implementation of your class :

    
class Vect
{
private:
float xcoord;

public:
inline float getx() const
{
return xcoord;
}

inline void setx( float value)
{
xcoord = value;
}

};


This way, accesses to xcoord should be as fast as if it were accessed directly.

Note : you don't need to use references to pass const standard type arguments (int/float/char/...), you won't have any speed increase for this.

Edited by - Prosper/LOADED on January 29, 2002 7:44:25 AM

Share this post


Link to post
Share on other sites
Sandman    2210
well, I'd use public variables for a vector class, but if you are dead set on keeping them private you can always declare the functions inline.

eg
      

inline float Vect::GetX(void)const ;




[edit]

too slow


Edited by - Sandman on January 29, 2002 7:49:11 AM

Share this post


Link to post
Share on other sites
BSXrider    122
Ahhh. I tried to "inline" my functions as another test but it was coming up as errors, didn''t realise thery ahd to go with the definitions.

3.9 seconds.

Good stuff

- seb

Share this post


Link to post
Share on other sites
BSXrider    122
quote:

you don''t need to use references to pass const standard type arguments (int/float/char/...), you won''t have any speed increase for this.



Yeah I know, but my experiment in the first post shows that reference actually WAS slightly faster. However, with the tuples inlined the time is EXACTLY the same either way.

- seb

Share this post


Link to post
Share on other sites
Brother Bob    10344
Either you have a REALLY crappy compiler, or you are compiling a debug version (or both ).

If you want to do ANY kind of benchmarking, you should compiler a release version, preferably with full optimization. Benchmarking on debug code is useless, and does not say/mean anything.

Share this post


Link to post
Share on other sites
Brother Bob    10344
If you do compile a realease, then I apologize. And I use the MSVC 6 compiler myself, and it''s nowhere near crappy

Anywyas, if you don''t want to make your members public, then inlined functions is probbaly the fastest. Just try them and choose the fastest one.

Share this post


Link to post
Share on other sites
jenova    122
i find that very wierd too. vc++ should be inlining those functions due to their size.

To the vast majority of mankind, nothing is more agreeable than to escape the need for mental exertion... To most people, nothing is more troublesome than the effort of thinking.

Share this post


Link to post
Share on other sites
BSXrider    122
Just loaded up the options bit.

Under "Optimizations" there''s an option called "Inline function expansion". Don''t know what it means really but I changed it to "any suitable (from __inline) and it made no difference.

If I put the member functions inside the class definition then they''re automatically inlined, it just seems to be if you declare it in the class and have the function in a separate file that it doesn''t automaticvally inline them. Interestingly in this case it would let you speciify that they''re inlined either.

- seb

Share this post


Link to post
Share on other sites
Stoffel    250
PS: if your test is this simple, I would highly suggest not doing a timed trial at all. Write a program that calls each function to be examined and then look at the disassembly--that way you know exactly what you're talking about. I won't go through the pain and suffering of doing it (I already know how to--you should learn), but I guarantee that these methods all compile to the same code.

also, re:
quote:

If I put the member functions inside the class definition then they're automatically inlined, it just seems to be if you declare it in the class and have the function in a separate file that it doesn't automaticvally inline them. Interestingly in this case it would let you speciify that they're inlined either.


inline is a lot like #define macros, so whoever uses the inlined function has to have the definition of the function. If code doesn't, then the compiler will silently put the function out of line and replace it with a function call; in this way it's different than a macro, because in this case a macro would give you an error.

Edited by - Stoffel on January 29, 2002 4:57:28 PM

Share this post


Link to post
Share on other sites
BSXrider    122
Stoffel: no offence but surely a timed trial is a good idea? The assembler of all the options I listed better had NOT be the same - if it is then there''s a lot of wasted complexity in c++ !

- seb

Share this post


Link to post
Share on other sites
Martee    476
Timed trials can be useful, but they can also be rather inaccurate. There are too many variables. Background processes, page faults, disk caching, position of the hard drive''s read head, contents of the CPUs'' cache, and so on. Looking at the disassembly is the best way to avoid all that, and see _exactly_ what your compiler is doing.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
I don''t know if someone else mentioned this, but you do know that you do not have to declare member functions as inline w/ the actual "inline" keyword, don''t you? If you just define the functions right inside a class interface, it''s inlined. Saves some typing, as well.

Share this post


Link to post
Share on other sites
Shannon Barber    1681
Do you have the standard or professional version of MSVC?
AFAIK, only the proferssional version has all the compiler optimizations (i suspose enterprise does too).

In a debug build those accessors won't be inlined, no matter what. Only in a release build. So again, if it truely is a time-critical piece of code, go public.

Standard timing methods are highly imprecise, and often inaccurate. It's a pre-emptive multi-threaded system, so you not inly measuring the time in your application, you're measuring time in other applications as well as in IRS (interraupt service routines).
You will measure _more_ accurately if you time for *less* than 10ms, because it is less likely that your app will be task-swapped during such a small interval. You will still be measuring time in ISRs.

How fast is your computer? The time for that loop ought to be less than half a second on anything around a gig.

Edited by - Magmai Kai Holmlor on January 29, 2002 9:57:43 PM

Share this post


Link to post
Share on other sites
FLCman    122
Maybe I don''t know what I''m talking about but 3.9 secs or whatever is pretty darn good for 1 billion (1,000,000,000) iterations through your loop. I would tend to think if you wanted to find out how long a single execution of that loop takes divide 3.9 sec / 1,000,000,000 to find out how long it took to run. I think it comes out to 3.9 ns for the loop to complete 1 iteration. What was the point of your benchmark? It doesn''t really come out as obvious to me. Then again I am brain dead when I''m at work. Just my 0.02 cents.

Share this post


Link to post
Share on other sites
Shannon Barber    1681
It ought to be 1tick (1ns on a gig) due to pipelining (or less with super-scaling, e.g. an Athlon XP).

...
Actually it's the same memory hole so super-scaling won't help. An XP may be able to set x,y,&z in the same amount of time as just setting x.

Edited by - Magmai Kai Holmlor on January 30, 2002 1:46:25 AM

Share this post


Link to post
Share on other sites
BSXrider    122
I''m a scientist, I know pretty much how to conduct a fair trial. Anything unnecessary to the running of windows was closed down, and I ran each test 3 times.

MKH: A have the pro versio, yes. And yes this is a release compile. 1/2 a second? I''d be very impressed. Try it on yours and see what you get.

- seb

Share this post


Link to post
Share on other sites
Stoffel    250
I don''t know what you call a scientist, but we''re all engineers here. Common legend has it that scientists trust theory while engineers trust results. Seeing as how my advice is so distasteful to you, I''ll just have to do the work myself and hope you''ll listen to me in the future (hey, I do that when I work with other scientists too--hmm, maybe it''s a course in scientist school, "How To Ignore your Engineers").

  
#include <cstdlib>

class Test
{
int m_priVar;
public:
int m_pubVar;
int getPrivVar () { return m_priVar; }
};

int GettingPublicVar (Test &t)
{
return t.m_pubVar;
}

int GettingPrivateVar (Test &t)
{
return t.getPrivVar ();
}

Disassembly:

PUBLIC ?GettingPublicVar@@YAHAAVTest@@@Z ; GettingPublicVar
; COMDAT ?GettingPublicVar@@YAHAAVTest@@@Z
_TEXT SEGMENT
_t$ = 8
?GettingPublicVar@@YAHAAVTest@@@Z PROC NEAR ; GettingPublicVar, COMDAT

; 13 : return t.m_pubVar;

mov eax, DWORD PTR _t$[esp-4]
mov eax, DWORD PTR [eax+4]

; 14 : }

ret 0
?GettingPublicVar@@YAHAAVTest@@@Z ENDP ; GettingPublicVar
_TEXT ENDS
PUBLIC ?GettingPrivateVar@@YAHAAVTest@@@Z ; GettingPrivateVar
; COMDAT ?GettingPrivateVar@@YAHAAVTest@@@Z
_TEXT SEGMENT
_t$ = 8
?GettingPrivateVar@@YAHAAVTest@@@Z PROC NEAR ; GettingPrivateVar, COMDAT

; 18 : return t.getPrivVar ();

mov eax, DWORD PTR _t$[esp-4]
mov eax, DWORD PTR [eax]

; 19 : }

ret 0
?GettingPrivateVar@@YAHAAVTest@@@Z ENDP ; GettingPrivateVar
_TEXT ENDS

The compiler generates the exact same types of instructions for each method, therefore there is no difference between the two, regardless of what your timed trials tell you.

Share this post


Link to post
Share on other sites
BSXrider    122
quote:
Original post by Stoffel
PS: if your test is this simple, I would highly suggest not doing a timed trial at all. Write a program that calls each function to be examined and then look at the disassembly--that way you know exactly what you''re talking about. I won''t go through the pain and suffering of doing it (I already know how to--you should learn), but I guarantee that these methods all compile to the same code.


quote:
Original post by BSXrider
The assembler of all the options I listed better had NOT be the same - if it is then there''s a lot of wasted complexity in c++ !



quote:
Original post by Stoffel
hope you''ll listen to me in the future



We have a bit of a comms tangle here. I did listen to your post, too closely in fact. It seemed to me that you said "these methods all compile to the same code". If you''d said "both" instead of "all" I might have seen your point, but instead I inferred that you meant ALL 5 of the options I''d listed. You see. My apologies

I agree with you on that disassembly though. Which is pretty much what options (4) and (5) in my original post determined, that the results were close enough the same. Because putting the function body in the class like you''ve done makes it automatically inlined.

quote:
Original post by Kylotan
Did you conduct the tests in every possible order to avoid any order effects?



I knew someone would ask that but couldn''t think of a concise way of wording it in my post. Yes, I repeated them in differing orders (ctrl-z and ctrl-y were well used )

- seb

Share this post


Link to post
Share on other sites
Shannon Barber    1681
quote:
Original post by BSXrider
MKH: A have the pro versio, yes. And yes this is a release compile. 1/2 a second? I'd be very impressed. Try it on yours and see what you get.


If you remove the grossly inefficent accessors, the optimizing version of MSVC will eliminate that loop.
As such, it takes 0.000000000 seconds on my computer.
One other thing (that I missed earlier) that loop isn't just coping numbers around - it's performing a full-blown ANSI/IEEE interger to floating point conversion - an Expen$ive operation.

IFF you insist on using an accessor, you need to return a non-const&.

        
class Vect
{
public:
float& x(){return v.x;}
}


[edit: I need to learn how to type]

Edited by - Magmai Kai Holmlor on January 30, 2002 8:33:42 PM

Share this post


Link to post
Share on other sites
Big B    337
quote:
Original post by Stoffel
hmm, maybe it''s a course in scientist school, "How To Ignore your Engineers").





I believe thats a Marketing / Management class.


If the wind blows hard enough, even turkeys can fly

Share this post


Link to post
Share on other sites