tags:

views:

63

answers:

3

I have a vector class that has addition, multiplication, subtraction, division, etc operators. I'm trying to optimize my program (which does a lot of vector operations) and I'm realizing that about 50% of the time spent is in constructing and destructing vectors. I understand that this is because every time I call a non-compound mathematical operator for a vector, a new vector is constructed. Is there a way to prevent this without using compound operators or expanding vector operations?

If I have:

Vector a = Vector(x, y, z);
Vector b = Vector(a, b, c);

Vector c = a + b;

I can't use += because c is a completely new vector. I know I can speed it up with this:

c.x = a.x + b.x;
c.y = a.y + b.y;
c.z = a.z + b.z;

but that doesn't seem as clean as just using an operator.

+1  A: 

Make sure you have optimizations turned on and that your compiler is applying RVO, which is designed for exactly this situation (but not required to be used). (You may have to use a form of NRVO in your op+ implementation, example below, which helps the compiler recognize and apply RVO.) Also, have you looked at blitz++?

Vector operator+(Vector const& a, Vector const& b) {
  Vector nrvo;
  // or: Vector nrvo (ctor, parameters, here);
  //...
  return nrvo;
}


There are other alternatives too, such as doing an explicit copy and then using op+=, which serves in a situation where RVO doesn't apply:

Vector c; // created somewhere else, and we want to assign to it
// instead of create it "in-place" as RVO does

Vector a, b;
// instead of:
//c = a + b
// use:
c = a;
c += b;

This can be achieved with expression templates, like blitz++ uses, without changing your syntax from c = a + b.

Roger Pate
+2  A: 

I understand that this is because every time I call a non-compound mathematical operator for a vector, a new vector is constructed. Is there a way to prevent this without using compound operators or expanding vector operations?

Well, the nature of adding two things together to produce a third thing requires you to construct a third thing...so how is what you're asking even logically possible?

That being said, if you're concerned about the temporaries created by using the addition operator, these may be optimized out by the compiler if your compiler supports return value optimization. Alternatively, if your compiler doesn't support this and you really want to cut back on temporaries but keep the + operator, you may want to look into emulating C++0x move semantics, and provide your vector with a rvalue move constructor, which will be invoked when it returns a temporary by value. See the Section titled "Moving Objects" in this article for information on implementing move semantics in C++03. Once C++0x comes out, you can just replace these hacks with real move constructors using the && operator for rvalue references.

Charles Salvia
Well suppose the third vector already is constructed. I only want to modify its components, not create a new vector and copy the components of the new vector to the already constructed one. This is a waste. Also, if I were doing multiple operations in one line, a new vector would be created for each of these operations which is unnecessary.
Stewart
A sure way to cut down on the temporaries created is to emulate C++0x move semantics by implementing a move constructor and a move assignment operator for your Vector class. You'll need to wrap the temporaries you return in something like a `MyVector_move_t` class or whatever. See the article I refer to in my post edited post for more information on doing this. The best part is that when C++0x comes along, you can just replace your fake move constructors with real move constructors.
Charles Salvia
+1  A: 

Whoa there. Your code is totally inefficient:

Vector a = Vector(x, y, z);
Vector b = Vector(a, b, c);

That's just inefficient. What you want to write is

Vector a(x, y, z);
Vector b(a, b, c);
rlbond