iDevGames Forums
Custom Primatives... faster? - Printable Version

+- iDevGames Forums (
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Game Programming Fundamentals (/forum-7.html)
+--- Thread: Custom Primatives... faster? (/thread-4639.html)

Pages: 1 2

Custom Primatives... faster? - KiroNeem - Jan 3, 2006 10:09 PM

I have looked at code here and there, and I have notices a few differences with how people program geometric primitives. The particular thing that I noticed was custom primitives. Sometimes with structs, arrays, or even classes to represent paired data like 2D and 3D points.

Although I'm unsure of the purpose of this. Is code using custom geometric primitives used for speed, or is it just organization of code?

Custom Primatives... faster? - akb825 - Jan 4, 2006 12:08 AM

If you're talking about structs or classes, those aren't custom primitives, but custom types. Primitives would be things such as int and double. I'd say that custom primitives would be typedefed primitives.

As for using custom data types, I'd say it's more about the organization. I doubt there would be much speed difference between accessing a member of a struct and accessing a member of an array. (it's more or less the same thing)

Custom Primatives... faster? - KiroNeem - Jan 4, 2006 08:13 AM

I do admit that there are many things you can do with those custom types that can speed production along. For example addition, subtraction, dot-products, cross-products, etc. I guess the only reason I have not done them is I'm just worried about speed, since variables like 3D points will be thrown around everywhere in my programs.

Custom Primatives... faster? - KiroNeem - Jan 4, 2006 09:13 AM

So I decided to build a simple speed tester to see the speeds for myself, and here are the results I was given.

Each operation was performed 100,000,000 times
Each operation takes three int[3] and adds two of them to the other
three[0] = one[0] + two[0];
three[1] = one[1] + two[1];
three[2] = one[2] + two[2];

CPP class operator: 2.4 Seconds
CPP class with c function: 1.6 Seconds
Writing directly in C: 0.1 Seconds
C function: 0.8 Seconds

I then went ahead and added inline to all the functions, although for some reason I got slower times Huh

Custom Primatives... faster? - Dan Potter - Jan 4, 2006 09:30 AM

It could be because in a lot of cases memory footprint is more useful than inlining. That's why Xcode defaults to -Os on PPC.

There are a lot of variables there in your tests. Any compiler worth its salt should be able to take things like:

struct Foo {
   int x, y, z;
   Foo operator+( const Foo & o ) const {
      Foo r;
      r.x = x + o.x;
      r.y = y + o.y;
      r.z = z + o.z;
      return r;

Foo a, b;
Foo c(a + b);

And turn it into pretty much the equivalent of the C code. IIRC there was some debate a while back at my job about using the constructor like that at the end vs using the implicit operator= ... too arcane for me to remember this early in the morning. Smile But as you can see it's a very nuanced issue.

Custom Primatives... faster? - DoG - Jan 4, 2006 03:32 PM

gcc does fairly well with inlined C++ and C. I usually get very acceptable speeds by making non-virtual, mostly inlined classes for geometric primitives such as matrices and vectors. The only way to get even faster is to use streaming together with altivec.

In my experience, inlined C++ is not slower than inlined C, usually.

Custom Primatives... faster? - OneSadCookie - Jan 4, 2006 06:29 PM

In fact, until GCC 3.3, it was usually faster Smile

Custom Primatives... faster? - KiroNeem - Jan 4, 2006 09:54 PM

Actually I'm surprised they do not go faster when I have used them. Don't they insert it's code into the place of the function call during compiling?

Custom Primatives... faster? - PowerMacX - Jan 5, 2006 09:56 PM

KiroNeem Wrote:Actually I'm surprised they do not go faster when I have used them. Don't they insert it's code into the place of the function call during compiling?

If you are trying to use inline with C++ methods, then it won't work. You need to put the methods you want to inline directly in the header for the compiler to inline them, like this:

*  CVector3.h
*  Created by Ignacio on Wed Jul 23 2003.

#ifndef __CVECTOR3_H__
#define __CVECTOR3_H__

#include <cmath>

#ifndef PI
#define PI 3.14159265359f

class CVector3
    float x;
    float y;
    float z;

    CVector3()                                    { x = 0.0f; y = 0.0f; z = 0.0f; };
    CVector3(float X, float Y, float Z)            { x = X; y = Y; z = Z; };
    CVector3 operator+(const CVector3& v) const    { return CVector3(v.x + x, v.y + y, v.z + z); };
    CVector3 operator-(const CVector3& v) const    { return CVector3(x - v.x, y - v.y, z - v.z); };
    CVector3 operator*(float num) const            { return CVector3(x * num, y * num, z * num); };
    CVector3 operator/(float num) const            { float ratio = 1.0f/num; return CVector3(x * ratio, y * ratio, z * ratio); };
    void operator=(const CVector3& v)            { x = v.x; y = v.y; z = v.z; };
    void operator+=(const CVector3& v)            { x += v.x; y += v.y; z += v.z; };
    void operator-=(const CVector3& v)            { x -= v.x; y -= v.y; z -= v.z; };
    void operator*=(float num)                    { x *= num; y *= num; z *= num; };
    void operator/=(float num)                    { float ratio = 1.0f/num; x *= ratio; y *= ratio; z *= ratio; };
    float    Magnitude() const                    { return sqrt(x*x + y*y + z*z); };
    float    Magnitude2() const                    { return (x*x + y*y + z*z); };
    void     Normalize()                         { float ratio = 1.0f/Magnitude(); x *= ratio; y *= ratio; z *= ratio; };
    CVector3 Normalized() const                    { float ratio = 1.0f/Magnitude(); return CVector3(x*ratio,y*ratio,z*ratio); };
    float    Dot(const CVector3& v) const        { return (x*v.x + y*v.y + z*v.z); };
    float    Angle(const CVector3& v) const;
    float    AngleX() const                        { return atan2(-y,x); };
    float    AngleZ() const                        { return atan2(-y,z); };
    float    AngleY() const                        { return atan2(-x,z); };
    CVector3 Cross(const CVector3& v) const        { return CVector3((y*v.z - z*v.y),(z*v.x - x*v.z),(x*v.y - y*v.x)); };
    void     MutateBy(const CVector3& v);
    CVector3 MutatedBy(const CVector3& v) const;
    void     Print() const;
    void     Print(const char *objectName) const;

In this example 3D vector class, every method is inlined, except for Angle, MutateBy, MutatedBy & both Prints, which have their code written as usual on the .cpp file. Note that the "inline" keyword is not even necessary.

Custom Primatives... faster? - DoG - Jan 6, 2006 03:04 AM

Actually, inline with C++ has the same restrictions as inline in C. The function definition must be included for it to work. Additionally, virtual functions cannot be inlined, as the implementation to call is decided at runtime.

When I said inlined C++ is just as fast, I was comparing it to inlined C.

Custom Primatives... faster? - zKing - Jan 6, 2006 01:29 PM

Note the inline is just a 'suggestion' to the compiler, it can pick and choose what to do case by case (including ignoring all your suggestions). On top of this, depending on your compiler optimization settings it may inline functions for speed that you didn't mark as inline. Basically its all _extremely_ compiler dependant.

Secondly, inlining can make your code slower... because it makes it larger. Why? If your code begins to grow in size such that it no longer fits nicely into the CPU caches or causes some boundry case memory paging.

I think this belongs under...
"Premature optimization is the root of all evil." - Donald Knuth

I'd also add that optimization without first measuring and then making a goal for what metrics you want to hit is pointless. Or to put it another way:

1) Build it as simple as possible so that it is bug free and it works correctly.

2) Measure its performance and determine what needs to be faster and where you can realistically improve it.

3) Make very targeted fixes to improve performance. Remember that design/algorithm changes almost always have _far_ more performance effect than one line 'speed ups'.

Oh and you want to know the magic wand for solving performance problems, schedule problems, man power problems, budget problems... just about every software development problem?:
Cut features.

In my experience this is the most consistently succesful solution to a project that is out of control in one way or another.

Custom Primatives... faster? - akb825 - Jan 6, 2006 01:33 PM

Assuming you have optimizations enabled, the compiler might inline for you, which will make it a moot point. Also, you can't inline with a loop. (I'm sure you can't with recursion, either)

Custom Primatives... faster? - DoG - Jan 6, 2006 03:53 PM

Functions in loops do get inlined, but loop unrolling is another issue. Recursion can be inlined up to a certain extent.

How inline behaves with gcc at least is well documented. See

Nowadays, one can expect sane behaviour from most compilers.

Unless you tell gcc to do otherwise, and honouring the other requirements for a function to be inlined, inline behaves as expected. Obviously, inline is an optimisation, so optimisations have to be turned on.

Speaking of math primitives, it doesn't take much brains to inline a function that adds a few numbers if things get slow. A function call adding a few dozen instructions takes several times longer to execute than the function body itself. Usual optimisation steps apply, eg profile first, but this is really one of the prime cases inlining was meant be used for.

Custom Primatives... faster? - akb825 - Jan 6, 2006 04:47 PM

DoG Wrote:Functions in loops do get inlined
Yes, but functions that contain loops can't be inlined. Rasp

Custom Primatives... faster? - DoG - Jan 6, 2006 05:11 PM

akb825 Wrote:Yes, but functions that contain loops can't be inlined. Rasp

That is nonsense. RTM.