In matlab we can use the matlab operator as follows:
M=[1 2 3 4, 5 6 7 8, 9 10 11 12]
M[:,1] = M[:,2] + M[:,3]
to apply the same operation to all the rows of a matrix
I'am wondering if we can apply a same operation to set values to a range of values in std::vector as it's done with colon(:) matlab's operator. Indeed, I'm using a vector to store the matrix values.
vector<int> M;
Thanks in advance.
There are C++ libraries that allow one to handle matrices pretty much as matlab does (allowing also for SIMD vectorization); you may want to consider eigen, for instance.
If you don't want to rely on external library you may want to consider std::valarray which has been explicitly thought for algebraic computations (with valarrays you may use std::slices to extract submatrices as you need).
You can define a "free" operator that takes std::vector<int> as parameters:
std::vector<int> operator +(const std::vector<int> &a, const std::vector<int> &b)
{
std::vector<int> result(a); // Copy the 'a' operand.
// The usual matrix addition is defined for two matrices of the same dimensions.
if (a.size() == b.size())
{
// The sum of two matrices a and a, is computed by adding corresponding elements.
for (std::vector<int>::size_type i = 0; i < b.size(); ++b)
// Add the values of the 'b' operand.
result[i] += b[i];
return result;
}
}
int main(int argc, char **argv)
{
std::vector<int> a;
std::vector<int> b;
// The copy constructor takes care of the assignement.
std::vector<int> c(a + b);
return 0;
}
The implementation of the operator + is quite naive, but is just an idea. Beware!, i've placed a ckeck before the add operation, if the check isn't passed a copy of the a operand is returned, i think that this will not be your desired behavior.
I've placed the operator in the same file of main but you can place it wherever you want as long as it is visible where the operation is performed.
Of course, you can define the operators you want in order to chain operations to achieve some more complex operations.
My maths concepts are quite old, but i hope it helps.
Related
I'm writing a two-dimensional wrapper around std::vector and would like to have a member returning a vector pointing to a subset of the class data vector e.g.
class matrix2D{
// ...
int nR, nC;
std::vector<float> data;
// ...
}
std::vector<float> matrix2D::row(int row){
return std::vector(data.begin()+row*nCols,data.begin()+row*nCols+nCols);
}
EDIT: I was mostly interested in this in order to be able to modify an entire row (and column as well) in place e.g. mat.row(r) = std::vector<float> (nR, 0.0);
I've written operator overloads that allow me to sum element-wise two matrix2D objects or a matrix2D and a scalar value, as well as an operator () overload that allows me to modify or access a particular matrix element in place i.e. float& operator()(int _r, int _c); The row method above returns a copy of the row data, and although inefficient, works from an access standpoint. I have also a void setRow(std::vector<float> _row) that modifies an entire row, but was wondering if there was an alternative way.
Since your class is a 2d matrix, you may want to be able to return a subset of the vector's data which isn't necessarily a sequential range in the vector. For example you may want to return a single column of the matrix, even though it appears you are storing it in row-major order, or you may want to return diagonal elements of the matrix. If this is the case, the solutions given in the comments (which suggest to return a pointer into the vector data, or to return a pair of iterators) won't work, since you would need to exclude certain elements among the range specified by those values.
If this is the case, one thing you could do is return a vector of ints which are indices into the matrice's data vector. This vector of indices would be what you are looking for: a subset which does not necessarily appear sequentially in the data vector.
You could overload the matrix2D's subscript operator to accept such a collection and return a special temporary type with assignment semantics for the subset of the matrix2D, so you could write code like:
int main(int argc, char **argv) {
matrix2d matrix4x4(4, 4);
std::vector<float> values(4, 1);
auto first_column = matrix4x4.first_column();
matrix4x4[first_column] = values;
matrix4x4.print();
// output is:
// 1 0 0 0
// 1 0 0 0
// 1 0 0 0
// 1 0 0 0
}
That way you could not only access subsets of values in the matrix, but also modify the subset.
Here is a quick implementation of this idea which should demonstrate the above example: https://ideone.com/j5DfBg
Obviously you could make a lot of improvements on that design, but hopefully you get the point.
Is it possible in Eigen to do the equivalent of the following operation in Matlab?
A=rand(10,10);
indices = [2,5,6,8,9];
B=A(indices,indices)
I want to have a submatrix as a view on the original matrix with given, non consecutive indices.
The best option would be to have a shared memory view of the original matrix, is this possible?
I've figured out a method that works but is not very fast, since it involves non vectorized for loops:
MatrixXi slice(const MatrixXi &A, const std::set<int> &indices)
{
int n = indices.size();
Eigen::MatrixXi B;
B.setZero(n,n);
std::set<int>::const_iterator iInd1 = indices.begin();
for (int i=0; i<n;++i)
{
std::set<int>::const_iterator iInd2=indices.begin();
for (int j=0; j<n;++j)
{
B(i,j) = A.coeffRef(*iInd1,*iInd2);
++iInd2;
}
++iInd1;
}
return B;
}
How can this be made faster?
Make your matrix traversal col-major (which is default in Eigen) http://eigen.tuxfamily.org/dox-devel/group__TopicStorageOrders.html
Disable debug asserts, EIGEN_NO_DEBUG, see http://eigen.tuxfamily.org/dox/TopicPreprocessorDirectives.html, as the comment by Deepfreeze suggested.
It is very non-trivial to implement vectorized version since elements are not contiguous in general. If you are up to it, take a look at AVX2 gather instructions (provided you have CPU with AVX2 support)
To implement matrix view (you called it shared-memory) you'd need to implement an Eigen expression, which is not too hard if you are well versed in C++ and know Eigen codebase. I can help you to get started if you so want.
I am wondering if there is an efficient and concise way to do an element-wise multiplication of every row (or column) of an Armadillo C++ matrix by a vector. The row (or column) and vector are the same size.
For example, IF fmat::each_row() (and/or each_col()) could be used as an rvalue, I'd want something like this to compile (currently it won't compile):
#include <armadillo>
int main()
{
using namespace arma;
fmat m(20, 10);
fvec v(10); // a column vector
m.each_row() % v.t(); // Currently a compiler error.
return 0;
}
From Armadillo version 5.6 onwards the .each_col() and .each_row() methods were expanded to handle out-of-place operations. Hence your suggested approach
m.each_row() % v.t();
should compile, see http://arma.sourceforge.net/docs.html#each_colrow.
It looks like you're using the wrong operator. According to the documentation for .each_row() and .each_col(), you need to specify an in-place operation (such as +=, -=, /=, %=). In other words, instead of %, use %=, as below:
m.each_row() % v.t(); // wrong
m.each_row() %= v.t(); // right
Apart from the in-place operations, the only other allowed operation for .each_row() and .each_col() is "=" by itself.
I have to compute large sums of 3d vectors and a comparison of using a vector class with overloaded operator+ and operator* versus summing up of separate components shows a performance difference of about a factor of three. I know assume the difference must be due to construction of objects in the overloaded operators.
How can one avoid the construction and improve performance?
I'm espacially puzzled, because the following is afaik basically the standard way to do it and I would expect the compiler to optimize this. In real life, the sums are not going to be done within a loop but in quite large expressions (several tens of MBs in total pre executable) summing up different vectors, this is why operator+ is used below.
class Vector
{
double x,y,z;
...
Vector&
Vector::operator+=(const Vector &v)
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
Vector
Vector::operator+(const Vector &v)
{
return Vector(*this) += v; // bad: construction and copy(?)
}
...
}
// comparison
double xx[N], yy[N], zz[N];
Vector vec[N];
// assume xx, yy, zz and vec are properly initialized
Vector sum(0,0,0);
for(int i = 0; i < N; ++i)
{
sum = sum + vec[i];
}
// this is a factor 3 faster than the above loop
double sumxx = 0;
double sumyy = 0;
double sumzz = 0;
for(int i = 0; i < N; ++i)
{
sumxx = sumxx + xx[i];
sumyy = sumyy + yy[i];
sumzz = sumzz + zz[i];
}
Any help is greatly appreciated.
EDIT:
Thank you all for your great input, I have the performance now at the same level.
#Dima's and especially #Xeo's answer did the trick. I wish I could mark more than one answer "accepted". I'll test some of the other suggestions too.
This article has a really good argumentation on how to optimize operators such as +, -, *, /.
Implement the operator+ as a free function like this in terms of operator+=:
Vector operator+(Vector lhs, Vector const& rhs){
return lhs += rhs;
}
Notice on how the lhs Vector is a copy and not a reference. This allowes the compiler to make optimizations such as copy elision.
The general rule that article conveys: If you need a copy, do it in the parameters, so the compiler can optimize. The article doesn't use this example, but the operator= for the copy-and-swap idiom.
Why not replace
sum = sum + vec[i];
with
sum += vec[i];
... that should eliminate two calls to the copy constructor and one call to the assignment operator for each iteration.
But as always, profile and know where the expense is coming instead of guessing.
You might be interested in expression templates.
I implemented most of the optimizations being proposed here and compared it with the performance of a function call like
Vector::isSumOf( Vector v1, Vector v2)
{
x = v1.x + v2.x;
...
}
Repeatedly executing same loop with a few billion vector summations for every method in alternating order, did not result in the promised gains.
In case of the member function posted by bbtrb, this method took 50% more time than the isSumOf() function call.
Free, non member operator+ (Xeo) method needed up to double the time (100% more) of the is SumOf() function.
(gcc 4.6.3 -O3)
I aware of the fact, that this was not a representative testing, but since i could not reproduce any performance gains by using operators at all. I suggest to avoid them, if possible.
Usually, operator + looks like:
return Vector (x + v.x, y + v.y, z + v.z);
with a suitably defined constructor. This allows the compiler to do return value optimisation.
But if you're compiling for IA32, then SIMD would be worth considering, along with changes to the algorithms to take advantage of the SIMD nature. Other processors may have SIMD style instructions.
I think the difference in performance is caused by the compiler optimization here. Adding up elements of arrays in a loop can be vectorized by the compiler. Modern CPUs have instructions for adding multiple numbers in a single clock tick, such as SSE, SSE2, etc. This seems to be a likely explanation for the factor of 3 difference that you are seeing.
In other words, adding corresponding elements of two arrays in a loop may generally be faster than adding corresponding members of a class. If you represent the vector as an array inside your class, rather than x, y, and z, you may get the same speedup for your overloaded operators.
Are the implementations to your Vector operator functions directly in the header file or are they in a separate cpp file? In the header file they would typically be inlined in an optimized build. But if they are compiled in a different translation unit, then they often won't be (depending on your build settings). If the functions aren't inlined, then the compiler won't be able to do the type of optimization you are looking for.
In cases like these, have a look at the disassembly. Even if you don't know much about assembly code it's usually pretty easy to figure out what's different in simple cases like these.
Actually if you look at any real matrix code the operator+ and the operator+= don't do that.
Because of the copying involved they introduce a pseudo object into the expression and only do the real work when the assignment is executed. Using lazy evaluation like this also allows NULL operations to be removed during expression evaluation:
class Matrix;
class MatrixOp
{
public: virtual void DoOperation(Matrix& resultInHere) = 0;
};
class Matrix
{
public:
void operator=(MatrixOp* op)
{
// No copying has been done.
// You have built an operation tree.
// Now you are goign to evaluate the expression and put the
// result into *this
op->DoOperation(*this);
}
MatrixOp* operator+(Matrix& rhs) { return new MatrixOpPlus(*this,rhs);}
MatrixOp* operator+(MatrixOp* rhs){ return new MatrixOpPlus(*this,rhs);}
// etc
};
Of course this is a lot more complex than I have portrayed here in this simplified example. But if you use a library that has been designed for matrix operations then it will have already been done for you.
Your Vector implementation:
Implement the operator+() like this:
Vector
Vector::operator+(const Vector &v)
{
return Vector(x + v.x, y + v.y, z + v.z);
}
and add the inline operator in your class definition (this avoids the stack pushs and pops of the return address and method arguments for each method call, if the compiler finds it useful).
Then add this constructor:
Vector::Vector(const double &x, const double &y, const double &z)
: x(x), y(y), z(z)
{
}
which lets you construct a new vector very efficiently (like you would do in my operator+() suggestion)!
In the code using your Vector:
You did:
for(int i = 0; i < N; ++i)
{
sum = sum + vec[i];
}
Unroll this kind of loops! Doing only one operation (as it would be optimized to using the SSE2/3 extensions or something similar) in a very large loop is very inefficient. You should rather do something like this:
//Unrolled loop:
for(int i = 0; i <= N - 10; i += 10)
{
sum = sum + vec[i];
+ vec[i+1];
+ vec[i+2];
+ vec[i+3];
+ vec[i+4];
+ vec[i+5];
+ vec[i+6];
+ vec[i+7];
+ vec[i+8];
+ vec[i+9];
}
//Doing the "rest":
for(int i = (N / 10) * 10; i < N; ++i)
{
sum = sum + vec[i];
}
(Note that this code is untested and may contain a "off-by-one"-error or so...)
Note that you are asking different things because the data is not disposed in the same way in memory. When using Vector array the coordinates are interleaved "x1,y1,z1,x2,y2,z2,...", while with the double arrays you have "x1,x2,...,y1,y2,...z1,z2...". I suppose this could have an impact on compiler optimizations or how the caching handles it.
I wanted to use boost accumulators to calculate statistics of a variable that is a vector. Is there a simple way to do this. I think it's not possible to use the dumbest thing:
using namespace boost::accumulators;
//stuff...
accumulator_set<vector<double>, stats<tag::mean> > acc;
vector<double> some_vetor;
//stuff
some_vector = doStuff();
acc(some_vector);
maybe this is obvious, but I tried anyway. :P
What I wanted was to have an accumulator that would calculate a vector which is the mean of the components of many vectors. Is there an easy way out?
EDIT:
I don't know if I was thoroughly clear. I don't want this:
for_each(vec.begin(), vec.end(),acc);
This would calculate the mean of the entries of a given vector. What I need is different. I have a function that will spit vectors:
vector<double> doSomething();
// this is a monte carlo simulation;
And I need to run this many times and calculate the vectorial mean of those vectors:
for(int i = 0; i < numberOfMCSteps; i++){
vec = doSomething();
acc(vec);
}
cout << mean(acc);
And I want mean(acc) to be a vector itself, whose entry [i] would be the means of the entries [i] of the accumulated vectors.
Theres a hint about this in the docs of Boost, but nothing explicit. And I'm a bit dumb. :P
I've looked into your question a bit, and it seems to me that Boost.Accumulators already provides support for std::vector. Here is what I could find in a section of the user's guide :
Another example where the Numeric
Operators Sub-Library is useful is
when a type does not define the
operator overloads required to use it
for some statistical calculations.
For instance, std::vector<> does not overload any arithmetic operators, yet
it may be useful to use std::vector<>
as a sample or variate type. The
Numeric Operators Sub-Library defines
the necessary operator overloads in
the boost::numeric::operators
namespace, which is brought into scope
by the Accumulators Framework with a
using directive.
Indeed, after verification, the file boost/accumulators/numeric/functional/vector.hpp does contain the necessary operators for the 'naive' solution to work.
I believe you should try :
Including either
boost/accumulators/numeric/functional/vector.hpp before any other accumulators header
boost/accumulators/numeric/functional.hpp while defining BOOST_NUMERIC_FUNCTIONAL_STD_VECTOR_SUPPORT
Bringing the operators into scope with a using namespace boost::numeric::operators;.
There's only one last detail left : execution will break at runtime because the initial accumulated value is default-constructed, and an assertion will occur when trying to add a vector of size n to an empty vector. For this, it seems you should initialize the accumulator with (where n is the number of elements in your vector) :
accumulator_set<std::vector<double>, stats<tag::mean> > acc(std::vector<double>(n));
I tried the following code, mean gives me a std::vector of size 2 :
int main()
{
accumulator_set<std::vector<double>, stats<tag::mean> > acc(std::vector<double>(2));
const std::vector<double> v1 = boost::assign::list_of(1.)(2.);
const std::vector<double> v2 = boost::assign::list_of(2.)(3.);
const std::vector<double> v3 = boost::assign::list_of(3.)(4.);
acc(v1);
acc(v2);
acc(v3);
const std::vector<double> &meanVector = mean(acc);
}
I believe this is what you wanted ?
I don't have it set up to try right now, but if all boost::accumulators need is properly defined mathematical operators, then you might be able to get away with a different vector type: http://www.boost.org/doc/libs/1_37_0/libs/numeric/ublas/doc/vector.htm
And what about the documentation?
// The data for which we wish to calculate statistical properties:
std::vector< double > data( /* stuff */ );
// The accumulator set which will calculate the properties for us:
accumulator_set< double, features< tag::min, tag::mean > > acc;
// Use std::for_each to accumulate the statistical properties:
acc = std::for_each( data.begin(), data.end(), acc );