0

I'm writing numerical code, in which it is useful to define vector operations. E.g if x and y are n-long vectors full of floats, it is nice to have x^y result in a in the ith element of y equaling some arbitary function of the ith element of x. One simple way of doing this is:

#include <vector>
#include <stdio.h>
#include <ctime>

using namespace std;

template <typename T>
void operator^(vector<T> A, vector<T> B){
  typename vector<T>::iterator a = A.begin();
  typename vector<T>::iterator b = B.begin();
  while(a!=A.end()){
    *b = 2*(*a);
    a++; b++;
  }
//for (uint i=0; i<A.size(); i++)
  //B[i] = 2*A[i];
}

int main(int argc, char** argv){

  int n = 10000;
  int numRuns = 100000;
  vector<float> A;
  for (int i=0; i<n; i++)
    A.push_back((float) i);

  vector<float> B = vector<float>(n);
  clock_t t1 = clock();
  for (int i=0; i<numRuns; i++)
    for (int j=0; j<n; j++)
      B[j] = 2*A[j];
  clock_t t2 = clock();
  printf("Elapsed time is %f seconds\n", double(t2-t1)/CLOCKS_PER_SEC);

  t1 = clock();
  for (int i=0; i<numRuns; i++)
    B^A;
  t2 = clock();
  printf("Elapsed time is %f seconds\n", double(t2-t1)/CLOCKS_PER_SEC);

  return 0;
}

Now, when run on my computer after -O3 compiling, the output is

Elapsed time is 0.370000 seconds
Elapsed time is 1.170000 seconds

If instead I use the commented out lines in the template, the second time is ~1.8 seconds. My question is: how do I speed up the operator call? Ideally it should take the same amount of time as the hand-coded loop.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
andyInCambridge
  • 1,215
  • 2
  • 13
  • 27
  • C and C++ are not the same language. If they were, we'd probably use the same tag for them. – R. Martinho Fernandes Sep 25 '11 at 21:26
  • 1
    Don't write an operator to do this. Write a function. Doing this is one of the reason that operator overloading has gained such a bad reputation. When you make operators do stuff that is unexpected to everybody (except you) makes the code nearly imposable to read. – Martin York Sep 25 '11 at 21:42

2 Answers2

8

You're passing the arguments by value. That makes copies of the vectors.

template <typename T>
void operator^(vector<T> A, vector<T> B)

If you pass them by reference, you may get a speedup.

template <typename T>
void operator^(vector<T> const& A, vector<T>& B)

(A quick test on ideone.com shows even better performance than the hand-written loop, but I don't know what optimizations they enable on the compilation.)

On another note, you probably want to overload some other operator. It's bad style to have non-assignment and non-increment operators modifying their arguments (I recommend reading the Operator Overloading FAQ). You should overload operator^= instead.

template <typename T>
vector<T>& operator^=(vector<T>& B, vector<T> const& A){
  typename vector<T>::const_iterator a = A.begin();
  typename vector<T>::iterator b = B.begin();
  while(a!=A.end()){
    *b = 2*(*a);
    a++; b++;
  }
  return B;
}
Community
  • 1
  • 1
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
0

Another thought is to use valarrays, which were intended expressly for this purpose, and have a large number of operators defined for you already.

A description of their usage and operations can be found here: http://www.cplusplus.com/reference/std/valarray/

A discussion of them can be found here indicating some pros and cons: C++ valarray vs. vector

Community
  • 1
  • 1
loki11
  • 374
  • 1
  • 4