When to use Eigen::Vector vs std::vector? - c++

Because of external dependencies, I'm required to write some data in a Eigen::VectorXi container.
However, there are other times in which I'm not required to use en Eigen::VectorXi as a container, and I may use a standard std::vector<int>
Currently I have Eigen and std vectors sprinkled through my code. The only times in which I decide to use an std:vector is when I'll be making insertions on the fly, since resizing and reinserting is more tedious (and possibly computationally expensive) than using push_back(<value>)
I'd like to be sure that I'm using one or the other in the right time, instead of randomly choosing. What are the right instances to use Eigen::Vector instead of std::vector?

Classes in Eigen represent mathematical objects. In this case, a mathematical vector, with all the typical operations on vectors, like multiplication with a matrix or scalar product.
std::vector is essentially an (dynamic) array, storing a list of data in consecutive space. Typical operations would be appending data or sorting it.
When you decide what you want to use, simply ask yourself if this is a mathematical vector. You could extend both to hold what the other is supposed to, creating a scalar product over std::vector, but why would you? Eigen does that already. Using it for what it is intended makes it clear to everybody what you represent, increasing readability.

Related

Efficient memory allocation before iterative algorithm

I'm trying to implement an algorithm (C++) which is basically structured in the following way:
Build data structures which include
a) vector(double)
b) vector(vector(double)) (representing a sparse matrix A, inner vector
sizes not known a priori and also not the same)
Run an iterative algorithm performing lots of calculations on those
structures
To make it efficient I would like to make sure that before part two starts the memory is optimally allocated, so if possible that the vectors stored in A are next to each other in the memory without any overhead or anything. Is there a good way to do this?
If you want to make the creation of the vector more efficient you could use vector::reserve which reduces reallocation if append data to the vectors.
The access to the vectors is always as efficient as possible. The data in a std::vector is saved contiguously. That means that for big amounts of data it is not relevant if the inner vector are allocated nect to each other or not, because it need the same number of dereferencings.
In general I would say the STL is pretty efficient, but except for functions like reserve you can not do much to optimize it.
If you need higher speed you have to use a data structure that is optimized for your use case.

Class with Multidimensional Container

I am working on a Recurrent Neural Network in C++ using the Qt library. It gets constructed with a vector containing the topology where the number of elements define the number of layers and each element specifies the number of neurons in each layer.
The problem at hand is that the class needs to store some weights in matrices which depend on the size of the elements as well as their number is depended on the size of the vector. Required is a fast and efficient, index based access, 3 dimensional (of which one dimension differs in size) container. It does not necessarily be able to be resizable but AFAIK it can not be preallocated bevor the constructor, since size and number is given with the constructor.
I tried to store them in a nested vector but except from problems how to work with that I already read that nested vectors do not have a good performance, e.g.
typedef QVector < QVector < QVector < double> > > Weights;
I read something about ‘Dynamically Allocated Multi-Dimensional Arrays’ using arrays of pointer pointing to arrays of pointers pointing to ... and so on. This did not look very elegant.
Qt also provides some Matrix classes but since I can not preallocate them I neglected those.
Taking some additional library like Boost.
Another solution might be writing some class or custom container for my needs but I would rather not unless this is really the best way to do it.
So I am asking for advise what is the way to go here? Is there even a possibility to preallocate the memory or does it need to be dynamic?
Disclaimer: I am aware that there are a lot of similar questions around but they seem to lack comparing possibilities also I am not always sure if the underlying situation is the same.

Fastest way to convert from vector of pairs to two independent vectors in C++

lets say I have a vector of pair<int,int>. Now I want to extract the pair.first and pair.second as independent vectors. I can iterate on the vector and do that but is there a better/faster way?
In C++11, if you don't need the old vector anymore, you could perhaps get a tiny bit of extra efficiency from move semantics:
for (auto it = std::make_move_iterator(v.begin()),
end = std::make_move_iterator(v.end()); it != end; ++it)
{
v1.push_back(std::move(it->first));
v2.push_back(std::move(it->second));
}
Other than that, you certainly cannot do better than one loop. You will have to touch every element at least once, so this is as efficient as it gets.
Note that moving can only make a difference if the element types themselves have move semantics that are better than copying. This is not the case for ints, or any PODs. But it can't hurt to write your code generically so that you can take advantage of this in future situations.
If copying/moving is a problem, though, you should consider whether some view adapter for your original vector might be a better approach.
No there is not. The one thing to take care of is to use reserve on the two resulting vectors to prevent unnecessary reallocations.
You won't be able to avoid the iteration. As to the fastest solution,
it depends on what is in the pair, and on the actual implementation.
Depending on these, it may be better to create the target vectors with
the correct size, and assign to them; or to create them empty, and use
reserve and then push_back. You might also want to compare indexing
with using iterators; if you're using pre-sized vectors, using only one
control variable instead of three might be an improvement. (With g++,
the last time I measured, creating vectors of the correct size and
assigning was faster than using reserve and push_back, at least for
double. Despite the fact that it meant looping twice internally, and
initializing the values to 0.0.)
You might also want to try creating functional objects to extract the
first and second elements of the pair (supposing you don't have them
already), and use two calls to transform. Again, either with a
predimensionned vector or using a back inserter as target. Off hand, I
wouldn't expect this to provide better performance, but you never know.
You have to iterate over the vector anyway, so in terms of Complexity, this is as good as you can get.

Sharing an array with STL vectors

I would like to share the contents of an array of doubles a of size k with one or more STL vectors v1, v2...vn.
The effect that I want from this shared storage is that if the underlying array gets modified the change can be observed from all the vectors that share its contents with the array.
I can do that by defining the vectors v1...vn as vectors of pointers
vector<double*> v1;
and copy the pointers a to a + k into this vector. However, I do not like that solution. I want the vectors to be a vector of doubles.
Given that you can extract the underlying pointer from a vector I am assuming one could initialize a vector with an array in such a way that the contents are shared. Would appreciate help about how to do this.
Given that you can extract the underlying pointer from a vector I am assuming one could initialize a vector with an array in such a way that the contents are shared.
No, you can't do this. The Standard Library containers always manage their own memory.
Your best option is to create the std::vector<double> and then use it as an array where you need to do so (via &v[0], assuming the vector is non-empty).
If you just want to have the container interface, consider using std::array (or boost::array or std::tr1::array) or writing your own container interface to encapsulate the array.
This sounds to me like you want to alias the array with a vector. So logically you want a vector of references (which doesn't work for syntactical reasons). If you really really need this feature, you can write your own ref wrapper class, that behaves exactly like an actual C++ reference, so the users of your vn vectors wont be able to distinguish between vector<T> and vector<ref<T> > (e.g. with T = double). But internally, you could link the items in the vectors to the items in your "master" array.
But you should have darned good reasons to do this overhead circus :)
OK, Standard Library containers are both holders of information, and enumerators for those elements. That is, roughly any container can be used in almost any algorithm, and at least, you can go through them using begin() and end().
When you separate both (element holding and element enumeration), as in your case, you may consider boost.range. boost.range gives you a pair of iterators that delimit the extent to which algorithms will be applied, and you have the actual memory store in your array. This works mostly to read-access them, because normally, modifying the structure of the vector will invalidate the iterators. You can recreate them, though.
To answer your question, as far as I know std::vector can not be given an already constructed array to use. I can not even think how that could be done since there are also the size/capacity related variables. You can possibly try to hack a way to do it using a custom allocator but I feel it will be ugly, error prone and not intuitive for future maintenance.
That said, if I may rephrase your words a bit, you are asking for multiple references to the same std::vector. I would either do just that or maybe consider using a shared_ptr to a vector.

Linear multi-dimensional container

I require a linear vector container to behave like a multi-dimensional vector container. That is, a vector such as std::vector< std::vector< std::vector<int> > > be declared as std::vector<int> but behave as if it is multi-dimensional. This requires that I have set and get functions that allow accessing by multiple indices, rather than just one (that is, x, y, z and not just i).
The conversion is not the problem (that is, converting a 3D or 2D index to 1D), I am already doing that. However, I am starting to require the same conversion for several arrays. To make matters more complicated, I require a linear array to behave as if it is 2D, 3D and 4D. Now I want to make a container that will take care of the conversion internally. For all intents and purposes, the container will look like it is multi-dimensional, but it is in fact a linear array underneath.
So, first of, I am not sure whether libraries like boost have already something similar implemented. If so, please point me in the right direction. If not, then I would like to create one for my use but have a few questions.
My current approach is to make a class that has a vector container. There is a GetVec() function that will return the address of the std::vector so that I don't have to write all the functions that std::vector already has (getting the iterators, size etc.).
I want the user to be able to use the container from 1-D to N-D. When accessing, the user should be allowed to pass indexes that can represent a 1-D array or an N-D array. How do I ensure that the user is passing the correct number of indexes (in the function parameters)? Also, when initializing, the user should be able to specify the dimensions (variable parameter list?).
If this is a bad idea in general, please let me know but with good reasons. If not, any pointers on how to go about implementing this class would be much appreciated.
You have two choices: std::valarray (and its splice adapters), or boost::multi_array.
The first one lacks many things, and is not often used (it should deserve more love though). The second one is heavy but quite clean to use.
Also, you can have a look at Eigen if you intend to do linear algebra on those beasts.
I can also mention Intel Array Building Blocks which is simply awesome, and could be what you want in fine. It depends on what you do with those containers.