Public Group

# C++ arguments

This topic is 2566 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm curious is the way you pass arguments to functions effects speed.

For example, would A be faster than B?

A

//Header struct vertex {int x,y,z}; //Main Code setVetex(vertex coordinates);

B
//Main Code setVetex(int x, int y, int z);

Also the following appears very often in my code.
I want to make the code cleaner (vertex's opposed to 3 ints), however I dont want to make it more complicated and buggy then needed.
 setVertex(x+1,y,z); setVertex(x-1,y,z); setVertex(x,y+1,z); setVertex(x,y+1,z); setVertex(x,y,z-1); setVertex(x,y,z+1); 

How would I do this with the typedef?
Would I have to modify it then remodify it again before the next function?
ex:
 x+=1; setVertex(x,y,z); x-=1; 

Thanks
Walker

##### Share on other sites

I'm curious is the way you pass arguments to functions effects speed.

For example, would A be faster than B?

A

//Header struct vertex {int x,y,z}; //Main Code setVetex(vertex coordinates);

B
//Main Code setVetex(int x, int y, int z);

Assuing your setVertex A takes a parameter of type "vertex", then it's quite the opposite: B is probably faster than A. The reason for this is that the compiler will probably pass x,y, and z via register. It will have to pass the "vertex" struct via memory. You could, however, pass a const ref to setVertex instead. This would be as fast as passing the ints because it would use a register.

void setVertex(const vertex& vertexParameter) { // now it's not slow }

Also the following appears very often in my code.
I want to make the code cleaner (vertex's opposed to 3 ints), however I dont want to make it more complicated and buggy then needed.
 setVertex(x+1,y,z); setVertex(x-1,y,z); setVertex(x,y+1,z); setVertex(x,y+1,z); setVertex(x,y,z-1); setVertex(x,y,z+1); 

How would I do this with the typedef?
Would I have to modify it then remodify it again before the next function?
ex:
 x+=1; setVertex(x,y,z); x-=1; 
[/quote]

I might do:
 static const uint NUM_OFFSETS = 6; static const vertex vertexOffsets[NUM_OFFSETS] = { vertex(1, 0, 0), vertex(-1, 0, 0), vertex(1, 1, 0), vertex(1, -1, 0), vertex(1, 0, -1), vertex(1, 0, 1) }; vertex myVertex(x,y,z); for (uint i=0; i < NUM_OFFSETS; i++) { setVertex( myVertex + vertexOffsets ); } 

##### Share on other sites

Assuing your setVertex A takes a parameter of type "vertex", then it's quite the opposite: B is probably faster than A. The reason for this is that the compiler will probably pass x,y, and z via register. It will have to pass the "vertex" struct via memory. You could, however, pass a const ref to setVertex instead. This would be as fast as passing the ints because it would use a register.

void setVertex(const vertex& vertexParameter) { // now it's not slow }

You are guessing. In fact, what you've said does not even make sense. Passing a const vertex& means you've got a vertex somewhere and you're passing a pointer. Passing a vertex means you are (in x86 under most calling conventions) passing it on the stack. It will not "use a register" in either case. The compiler will not "probably pass x, y, and z via register" in either case. That's for x86 calling conventions. Now let's consider x86-64 calls. In both cases, passing a vertex and passing three ints will be done in registers. A const vertex& will not be.

Now let's do some educated guessing and consider the situation (on x86) that you've imagined where setVertex is defined in a header file, or the same file, or there is some cross-module optimization going on, and the compiler doesn't inline it but creates a special version of the function that you can call using just registers. In such a case, if passing a pointer to a vertex is more optimal than passing the three fields in a register, it will do so and produce the same code for a const vertex& and a vertex. If passing the fields of a vertex in registers is more optimal it will pass them in registers and it's certainly not harder to prove such an optimization if the parameter is a vertex rather than a const vertex&. In either case it's more information for the compiler than passing three int parameters, because how would the compiler know that these three parameters were originally packed contiguously in a struct? It would require more examination of the call sites for it to make such a presumption.

And even if the compiler makes the wrong decision it's not exactly a notable difference because the edge of the stack is practically the same thing as a register anyway.

##### Share on other sites
How is the edge of the stack practically the same as registers? It's stored in memory isn't it? Even if the processor prefetches it or whatever, I don't understand how it can be almost the same as registers.

##### Share on other sites

How is the edge of the stack practically the same as registers? It's stored in memory isn't it? Even if the processor prefetches it or whatever, I don't understand how it can be almost the same as registers.

That's a bit of an exaggeration, they aren't completely equivalent, but the edge of the stack is always in the L1 cache, except just after a thread switch. Edit: At that point it's really up to the CPU designers and the compiler as to how fast it goes.

##### Share on other sites
Have you profiled your application? My guess is that your bottleneck is elsewhere. I would pass using a structure because it groups together logically related information unless I had ample evidence that this was a poor decision.

##### Share on other sites

You are guessing. In fact, what you've said does not even make sense. Passing a const vertex& means you've got a vertex somewhere and you're passing a pointer. Passing a vertex means you are (in x86 under most calling conventions) passing it on the stack. It will not "use a register" in either case. The compiler will not "probably pass x, y, and z via register" in either case. That's for x86 calling conventions. Now let's consider x86-64 calls. In both cases, passing a vertex and passing three ints will be done in registers. A const vertex& will not be.

Now let's do some educated guessing and consider the situation (on x86) that you've imagined where setVertex is defined in a header file, or the same file, or there is some cross-module optimization going on, and the compiler doesn't inline it but creates a special version of the function that you can call using just registers. In such a case, if passing a pointer to a vertex is more optimal than passing the three fields in a register, it will do so and produce the same code for a const vertex& and a vertex. If passing the fields of a vertex in registers is more optimal it will pass them in registers and it's certainly not harder to prove such an optimization if the parameter is a vertex rather than a const vertex&. In either case it's more information for the compiler than passing three int parameters, because how would the compiler know that these three parameters were originally packed contiguously in a struct? It would require more examination of the call sites for it to make such a presumption.

And even if the compiler makes the wrong decision it's not exactly a notable difference because the edge of the stack is practically the same thing as a register anyway.

I'm not sure I understand. Are you under the impression that I implied that passing a (vertex) would yield x,y,z being passed in via registers? I didn't say that. I said that passing (int,int,int) would mean x,y,z get passed in via registers. I also said that would be faster than passing (vertex), which would be passed in on the stack (in x86, as you point out). Then I said that passing (const vertex&) was the right way, which seems to be what you are saying as well.

What I got wrong was saying passing (const vertex&) "[color="#1C2837"]would be as fast as passing the ints because it would use a register". Thanks for correcting, I didn't consider the pointer dereference. Given that the compiler is smart enough to optimize the call to use registers (and given that it didn't get inlined), however, I think you're agreeing that passing (const vertex&) is the right way.

Thanks for clearing it up.

##### Share on other sites
Hidden
All this speculation about whether stuff gets passed this way or that way, its all meaningless. Some functions that take a vertex sized type will be inlined, nothing will be passed. Other functions will be too large to inline, in which case the time spent passing the vertex will be negligible. The only definitive answer is to look at the Release assembly.

I have to change the numbers multiple times so I think I'm going to go with a mixture of the answers.
 //Header struct vertex {int x,y,z}; setVetex(int x, int y, int z); //Main Code vertex thisVertex; setVetex(thisVertex.x,thisVertex.y,thisVertex.z); 

Especially considering the following is shorter without passing the struct.
 setVetex(thisVertex.x+1,thisVertex.y,thisVertex.z); setVetex(thisVertex.x-1,thisVertex.y,thisVertex.z); setVetex(thisVertex.x,thisVertex.y+1,thisVertex.z); setVetex(thisVertex.x,thisVertex.y-1,thisVertex.z); setVetex(thisVertex.x,thisVertex.y,thisVertex.z+1); setVetex(thisVertex.x,thisVertex.y,thisVertex.z-1); 
The only problem is that it is a little (well alot) redundant.

Another question would functions be quicker if I declared the arguments as const's where possible?
 //A setVetex(int x, int y, int z); //B setVetex(const int x, const int y, const int z); 

##### Share on other sites

Another question would functions be quicker if I declared the arguments as const's where possible?
 //A setVetex(int x, int y, int z); //B setVetex(const int x, const int y, const int z); 

The const "can" be faster but it depends on the use/case involved. For instance, is the function defined in the header or in a cpp? If it is in the header you can ignore pretty much everything since a simple function such as this will inline given just about any compiler. But, even in this case the const "can" be faster based on usage since the non-const version could require the compiler to make copies of the values. Assume that the setVertex is non-const and it is in tight loop, prior to inlining the function the compiler may decide to make copies of the passed in data instead of just using it for the assignments. "Most" compilers should pinhole optimize away the copies since it will notice the fact that there are no changes being made. Of course depending on the complexity of the code involved and the compiler involved, this "may" not be caught and as such case the const version helps the compiler understand the intention and make sure the optimization of avoiding the copies is applied.

Const is a rule for your code to follow and a hint to the compiler, it really doesn't mean anything in the real code. But it "is" a good hint to include when and wherever you can since not all compilers are equal when it comes to doing the best optimizations possible.

Moving back to the prior comments about the speed in general, this is much more arcane than any simple answer can support. I look at the overall class and "not" any individual function in the class. For instance, what happens if/when you decide to change your vector to use SIMD math. SIMD is faster even in the case of 3 component floats but comes with some downfalls. Worse, some of the suggestions suck when you go to SIMD. Given this is the beginners area, I'll stick to the simple case that you should be as const correct as possible when defining your classes of this type.

I could go on for a while about many things involved in this, but it does not have much place in a beginners area.

• 18
• 11
• 16
• 9
• 50
• ### Forum Statistics

• Total Topics
631396
• Total Posts
2999783
×