C++ Speed Comparison

Started by
6 comments, last by Digitalfragment 20 years, 11 months ago
Im working on a simple math header file and have a question. Is it quicker to make classes with inline functions & overloaded operators ie: class Vec3 { public: // dont point this out, i know accessors and mutators etc. float x, y, z; inline vec3 operator+(vec3 v) { ... // whatever } }; OR, write simple typedefs and macro functions ie: typedef float vec3[3]; #define VECTOR_ADD(x, y) (x)[0] += (y)[0]; (x)[1] += (y)[1]; (x)[2] += (y)[2]
Advertisement
Don''t use macros, you don''t need them in this instance. If you use typedefs, a vector is not a first class object(you don''t have copy semantics).

use const references for the parameter, thats a start. as for the macro thing, bad idea. the operator + will be fine:

Vec3 operator + (const Vec3 & v);

you only need to mark it ''inline'' outside of the class declaration.

even if you were to do macros, why would you use that vec3[3] method, you could still use a class and let the macros access the x, y, z.
Called the "abstraction penalty" and varies greatly by compiler and with compiler optimization settings. In debug builds it will be slower, and in release builds both would be the same, ideally.

MSVC will optimize this no problem, for gcc, you''ll want a recent version, e.g. 3.2

Lastly, time both - look up the x86 opcode RDTSC.
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
"even if you were to do macros, why would you use that vec3[3] method, you could still use a class and let the macros access the x, y, z."

classes stored in memory use alot more space than simple arrays of primitives, so dont try to be smart.

<-------------------->

I know that the typedef is not a class - being a class isn''t of real importance, i just mean the memory size difference & the macro / inline function speed difference...
quote:Original post by Exorcist
"even if you were to do macros, why would you use that vec3[3] method, you could still use a class and let the macros access the x, y, z."

classes stored in memory use alot more space than simple arrays of primitives, so dont try to be smart.


  class vec3c{	float x, y, z;};typedef float vec3t[3];int main(int argc, char **argv){	cout << "sizeof(vec3c) = " << sizeof(vec3c) << endl;	cout << "sizeof(vec3t) = " << sizeof(vec3t) << endl;}  

And the output is (Intel C++ Compiler 6)
sizeof(vec3c) = 12sizeof(vec3t) = 12

Is that a lot more?
If you use classes and inline functions, you can shoot yourself in the foot by assuming that the compiler will perform certain optimizations (such as inlining). If you use macros, you can shoot yourself in the foot by blowing out the registers or cache.

One time I wrote a program that used class wrappers and lots of inline functions. The problem was that I was calling the inline functions in this manner: f(g(h(x))), and g() and h() called their own functions that I assumed would get inlined. The compiler ended up online inlining f() for some reason, so g() and h() were significantly slower than I had expected (and I did this in several classes that were used often). So the program was about 20 times slower than what I had expected. I was doing some other stupid things like passing by value (64-bit values), because I assumed it would be inlined. So don''t assume things will get inlined.

So after I shot off one foot by assuming things would be inlined, I promptly shot off my other foot and rewrote EVERYTHING as macros, thinking I would force the compiler to inline everything. What ended up happening is I turned those function calls into a single expression that was probably a few thousand characters long when expanded. This ended up being a hair slower than the version that used classes because (I guess) the registers were getting blown out, and probably wasn''t very cache friendly either.

My advice is to not write your program on the assumption that the compiler will perform a particular optimization (such as inlining), and to let the compiler decide when it is a good idea to inline or not. This may sound contradictory, but I think that''s part of becomming a good programmer. You have to learn how to balance things like saving your cache vs. unecessary function calls, keeping in mind things like good modular design, and so on.
quote:Original post by Exorcist
"even if you were to do macros, why would you use that vec3[3] method, you could still use a class and let the macros access the x, y, z."

classes stored in memory use alot more space than simple arrays of primitives, so dont try to be smart.


Something on the order of 32bytes per array... a litte bit but not that much considering one vector3D is 12bytes. If your arrays are 100 points long, it''s 2% overhead. Less if you make longer arrays. Besides, you can''t allocate the data on the stack anyway (unless all your data easily fits in <1meg). So unless you create all the array the exact same fixed size and they are always full, you can''t do better using a PoD array over a class array.

But it would to stupid to use a macro for access when you''ve got a class sitting there. Just make the elements public. Who in thier right mind is going to change the defintion of a 3D vector?
Accessors here are just going to make you debug builds slower.

quote:sjelkjd
If you use typedefs, a vector is not a first class object(you don''t have copy semantics).

Why not? It looks like a PoD to me - copy semantics are automatic. I would be inclined to make a class for the operator overloading, but you don''t need it for copying.
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

This topic is closed to new replies.

Advertisement