0

How to improve std::vector time? Hi i am making a software for multivariable fuzzy k means cluster. It work over big matrix´s 50.000 observations by 10 variables. The matrix not need to grow up o shrink or bounds check. Only make a resize to the needed size, load items and then make a lot of access.

First use:

`std::vector< std::vector<double> > matrix(NumClusters, std::vector<double>(NumObs,0.0));`

To get element do: double A=matrix[i][j]; But the procces time was of 20 minutes.

Then make:

std::vector<double> U(NumClusters *NumObs,0.0);   

To get element do: double A=U[i*NumObs+j]; and the time was better.

Now want to make a question: Which will be more faster to get access:

iterator+int

std::vector<double>::const_iterator Uit = U.begin();
double A= *(Uit+index)

pointer[int]

std::vector<double>::const_pointer Upt = U.data();
double A= Upt[index];

Or normal index access[int]

double A= U[index];

Greetings

user2232395
  • 461
  • 5
  • 15
  • 1
    `matrix[i][j]` your problem here is locality of data. Why don't you just test the other two options? In your example I would prefer the indexing because the iterator isn't doing anything for you and is *harder* to read. – Ed S. Jul 23 '15 at 22:49
  • 2
    all compilers should inline the operator[] into direct access to the pointer, so you cant get anything much faster than this. Maybe your bottleneck is somewhere else – Creris Jul 23 '15 at 22:51
  • It should be the same. The compiler should end up doing the same thing for either indexing or pointer access. – Petr Skocik Jul 23 '15 at 22:51
  • 1
    Profile your code instead of making fruitless assumptions – Captain Obvlious Jul 23 '15 at 22:53
  • @CaptainObvlious but, are those pointers restricted? – user3528438 Jul 23 '15 at 23:04
  • Struggling to find a question here. – Lightness Races in Orbit Jul 23 '15 at 23:10
  • What pointers? What restrictions are you talking about? Why do you think they are restricted? Why would they be restricted? Like I said, _profile your code_. – Captain Obvlious Jul 23 '15 at 23:13
  • 1
    Profile your code. In debug build access through iterator or `operator[]` most likely will be slower due to sanity checking performed by some compilers, but in release build I'd expect times for all methods to be nearly identical. – SigTerm Jul 23 '15 at 23:24
  • You need to know that STL containers have a non-negligible overhead, and that each individual allocation (each call to new) also has a non-negligible overhard (typically several tenths of bytes). When you create a vector< vector< something> >, this overhead becomes really significant (given that you have 50,000 observations). It will be more efficient to back everything in a single array (or a vector of structures). – BrunoLevy Jul 24 '15 at 13:18

2 Answers2

2

One thing you could try is switch rows and columns. If you have a 10 × 50,000 matrix and you lay it down one row after another, then operations on rows will be more efficient than operations on columns because they'll have better locality. You might also want to consider std::valarray as that container should optimize certain math operations on vector data.

As has been said, using indices vs. pointers shouldn't matter as far as efficiency is concerned. Indices could be more readable.

A very C++ thing you might want to do (which shouldn't have any effects on efficiency, just code readability) is wrap the vector in a container that makes it behave like a 2D matrix but uses a contiguous 1D vector underneath. Take a look at How can I use a std::valarray to store/manipulate a contiguous 2D array? for inspiration.

Community
  • 1
  • 1
Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
0

When you store 2D matrix as vector<vector<int>>, you have to dereference two pointers sequentally to access an alement (double indirection). That's why most of the libraries store matrices as linear array vector<int> as you do it now. In this case only single indirection is used, moreover all the data is stored in more compact layout in memory.

Now regarding fastest access. Ideally, all the three forms of access you mention are equally fast. However, no compiler is perfect, some may have issues with inlining deep calls (at least MSVC seems to have such issues rarely). That's why if you want to ensure maximal speed, you should avoid using any C++ abstractions inside your inner loop. Use only pointers and indices, and that would be the fastest way indeed. Note however, that most likely there will be no speedup over other methods (perhaps generated assembly would be absolutely equal).

As a conclusion, this way is the fastest for me:

auto ptr = matrix.data();
auto num = matrix.size();
for (size_t i = 0; i < num; i++)
    ptr[i] = ...; //do whatever complex math you have
stgatilov
  • 5,333
  • 31
  • 54