I noticed something strange about my code, and the amount of time it was taking to declare and initialize a 2D matrix of mine.
First way:
vector< vector<double> > gblStiff(dOF, vector<double>(dOF, 0));
dOF was some determined value earlier in the code. This first way took approximately 3 seconds when dOF = 30000!!
Second way:
double** gblStiff = new double*[dOF];
for (i=0; i < dOF; i++)
gblStiff[i] = new double[dOF];
This second way takes 0.063 seconds for the same dOF!!
Anyone able to shed light onto why this is happening? I am extremely curious.
This is really a C++ question. First, you probably didn't compile with optimisation. The vector template really needs a little compiler help to be usable. Second, vector's constructor initialises all of the elements; in your case, it initialises dOF*dOF doubles to zero. new double[dOF] does no such thing; that memory can contain anything at all.
Related
Disclaimer: I have limited knowledge of C++ due to switching from a college where they didn't teach C++ to another where it was the only language that was taught.
I'm trying to implement the box counting method for a randomly generated 2D cluster in a lattice that's 54x54.
One of the requirements is that we use a 1D array to represent the 2D square lattice, so a transformation is required to associate x and y values (columns and lines, respectively) to the actual positions of the array.
The transformation is "i = x + y*N", with N being the length of the side of the square lattice (in this case, it would be 54) and i being the position of the array.
The box-counting method, simply put, involves splitting a grid into large squares that get progressively smaller and counting how many contain the cluster in each instance.
The code works in the way that it should for smaller lattice sizes, at least the ones that I could verify (for obvious reasons, I can't verify even a 10x10 lattice by hand). However, when I run it, the box size goes all the way to 1/37 and gives me a "stack smashing detected" error.
From what I understand, the error may have something to do with array sizes, but I've checked the points where the arrays are accessed and made sure they're within the actual dimensions of the array.
A "for" in the function "boxTransform(int grid[], int NNew, int div)" is responsible for the error in question, but I added other functions that I believe are relevant to it.
The rest of the code is just defining a lattice and isolating the aggregate, which is then passed to boxCounting(int grid[]), and creating a .dat file. Those work fine.
To "fit" the larger array into the smaller one, I divide each coordinate (x, y) by the ratio of squares on the large array to the small array. This is how my teacher explained it, and as mentioned before, works fine for smaller array sizes.
EDIT: Thanks to a comment by VTT, I went back and checked if the array index goes out of bounds with the code itself. It is indeed the case, which is likely the origin of the problem.
EDIT #2: It was indeed the origin of the problem. There was a slight error in the calculations that didn't appear for smaller lattice sizes (or I just missed it).
//grid[] is an array containing the cluster
//that I want to analyze.
void boxCounting(int grid[]) {
//N is a global constant; it's the length of the
//side of the square lattice that's being analyzed.
//NNew is the side of the larger squares. It will
//be increased until it reaches N
for (int NNew = 1; N - NNew > 0; NNew++) {
int div = N/NNew;
boxTransform(grid, NNew, div);
}
}
void boxTransform(int grid[], int NNew, int div) {
int gridNew[NNew*NNew];
//Here the array elements are set to zero, which
//I understand C++ cannot do natively
for (int i = 0; i < NNew*NNew; i++) {
gridNew[i] = 0;
}
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
if (grid[col + row*N] == 1) {
//This is where the error occurs. The idea here is
//that if a square on the initial grid is occupied,
//the corresponding square on the new grid will have
//its value increased by 1, so I can later check
//how many squares on the larger grid are occupied
gridNew[col/div + (row/div)*NNew]++;
}
}
}
int boxes = countBox(gridNew, NNew);
//Creates a .dat file with the relevant values
printResult(boxes, NNew);
}
int countBox(int grid[], int NNew) {
int boxes = 0;
//Any array values that weren't touched remain at zero,
//so I just have to check that it's greater than zero
//to know if the square is occupied or not
for(int i = 0; i < NNew*NNew; i++) {
if(grid[i] > 0) boxes++;
}
return boxes;
}
Unfortunately this is not enough information to find the exact problem for you but I will try to help.
There are like multiple reasons that you should use a dynamic array instead of the fixed size arrays that you are using except if it's required in your exercise.
If you've been learning other languages you might think that fixed array is good enough, but it's far more dangerous in C++ than in most of the languages.
int gridNew[NNew*NNew]; You should know that this is not valid according to C++ standard, only the GCC compiler made it work. In C++ you always have to know the size of the fixed arrays in compile time. Which means you can't use variables to declare an array.
You keep updating global variables to track the size of the array which makes your code super hard to read. You are probably doing this because you know that you are not able to query the size of the array once you pass it to a function.
For both of these problems a dynamic array is the perfect solution. The standard dynamic array implementation in C++ is the std::vector: https://en.cppreference.com/w/cpp/container/vector
When you create a vector you can define it's size and also you can query the length of the vector with the size() member function.
Even better: You can use the at() function instead of the square brackets([]) to get and element with an index which does bounds check for you and throws an exception if you provided an index which is out of bounds which helps a lot to locate these kind of errors. Because in C++ if you just simply provide an index which does not exist in an array it is an undefined behaviour which might be your problem.
I wouldn't like to write any more features of the vector because it's really easy to find examples on how to do these things, I just wanted to help you where to start.
VTT was right in his comment. There was a small issue with the transformation to fit the large array into the smaller one that made the index go out of bounds. I only checked this on pen and paper when I should've put it in the actual code, which is why I didn't notice it. Since he didn't post it as an answer, I'm doing so on his behalf.
The int gridNew[NNew*NNew]; bit was kind of a red herring, but I appreciate the lesson and will take that into account when coding in C++ in the future.
I have a function which requires me to pass a fairly large matrix (which I created using Eigen) - and ranges from dimensions 200x200 -> 1000x1000. The function is more complex than this, but the bare bones of it are:
#include <Eigen/Dense>
int main()
{
MatrixXi mIndices = MatrixXi::Zero(1000,1000);
MatrixXi* pMatrix = &mIndices;
MatrixXi mTest;
for(int i = 0; i < 10000; i++)
{
mTest = pMatrix[0];
// Then do stuff to the copy
}
}
Is the reason that it takes much longer to run with a larger size of matrix because it takes longer to find the available space in RAM for the array when I set it equal to mTest? When I switch to a sparse array, this seems to be quite a lot quicker.
If I need to pass around large matrices, and I want to minimise the incremental effect of matrix size on runtime, then what is best practice here? At the moment, the same program is running slower in c++ than it is in Matlab, and obviously I would like to speed it up!
Best,
Ben
In the code you show, you are copying a 1,000,000 element 10,000 times. The assignment in the loop creates a copy.
Generally if you're passing an Eigen matrix to another function, it can be beneficial to accept the argument by reference.
It's not really clear from your code what you're trying to achieve however.
I'm looking to do some calculations and pass the resultant Jacobian NxN matrix and a right hand side vector(n) to boost's ublas and eventually ViennaCL.
The vector was no issue using copy(), however, the matrix is proving to be difficult. Any help would be greatly appreciated
// Global Variables
vector< vector<float> > Jacobian(0, vector<float>(0)); //Jacobian matrix
vector<float> delta_PQ; //rhs
//
// Set up some ublas objects
//
ublas::vector<ScalarType> rhs;
ublas::vector<ScalarType> result;
ublas::compressed_matrix<ScalarType> ublas_matrix;
using namespace boost::numeric;
typedef float ScalarType;
// Resize RHS from main program
resize_vector(rhs2, j_dimension);
ublas_matrix2.resize(j_dimension, j_dimension);
//copy content to GPU vector (recommended initialization)
copy(delta_PQ.begin(), delta_PQ.end(), rhs.begin()); //works
copy(Jacobian.begin(), Jacobian.end(), ublas_matrix); //won't compile
I have tried numerous variations and looked at the documentation:
http://ublas.sourceforge.net/refdoc/classboost_1_1numeric_1_1ublas_1_1compressed__matrix.html
Also, ViennaCL's example does not work for me:
http://viennacl.sourceforge.net/viennacl-examples-sparse-matrix.html
After a few hours of googling I decided to post on here in hopes someone else can crack it and it will be easier to find for the next person.
To close the loop on this I wanted to let everyone know what I did to solve my problem. Special thanks to Karl Rupp over at the ViennaCL project.
As an alternative, fill the ublas-matrix directly via operator(), i.e.
ublas_matrix(1,1) = value1;
ublas_matrix(7,8) = value2;
etc. Depending on the order of the values, filling ublas_matrix directly may be slower or faster than copy. As a rule of thumb, vector< map > is faster whenever the entries are written in a 'random' fashion, whereas ublas_matrix is faster if you fill row and column entries in consecutive order (and eventually supply the number of nonzero entries to the matrix constructor upfront).
all
I am using multidimensional STL vector to store my data in C++. What I have is a 3D vector
vector<vector<vector<double>>> vec;
What I want to retrieve from it is :
&vec[][1][]; // I need a pointer that points to a 2D matrix located at column 1 in vec
Anyone has any idea to do so? I would be extremly appreciate any help!
Regards
Long
It is best to consider vec just as a vector whose elements happen to be
vectors-of-vectors-of-double, rather than as a multi-dimensional structure.
You probably know, but just in case you don't I'll mention it,
that this datatype does not necessarily represent a rectangular cuboid.
vec will only have that "shape" if you ensure that all the vectors are
the same size at each level. The datatype is quite happy for the vector vec[j]
to be a different size from the one at vec[k] and likewise for vec[j][n]
to be a vector of different size from vec[j][m], so that your structure is "jagged".
So you want to get a pointer to the vector<vector<double>> that is at
index 1 in vec. You can do that by:
vector<vector<double>> * pmatrix = &vec[1];
However this pointer will be an unnecessarily awkward means of accessing that
vector<vector<double>>. You certainly won't be able to write the
like of:
double d = pmatrix[j][k];
and expect to get a double at coordinates (j,k) in the "matrix addressed
by a pmatrix". Because pmatrix is a pointer-to-a-vector-of-vector-of-double;
so what pmatrix[j] refers to is the vector-of-vector-of-double (not vector-of-double)
at index j from pmatrix, where the index goes in steps of
sizeof(vector<vector<double>>). The statement will reference who-knows-what
memory and very likely crash your program.
Instead, you must write the like of:
double d = (*pmatrix)[j][k];
where (*pmatrix) gives you the vector-of-vector-of-double addressed by pmatrix,
or equivalently but more confusingly:
double d = pmatrix[0][j][k];
Much simpler - and therefore, the natural C++ way - is to take a reference,
rather than pointer, to the vector<vector<double>> at index 1 in vec. You
do that simply by:
vector<vector<double>> & matrix = vec[1];
Now matrix is simply another name for the vector<vector<double>> at index 1 in vec,
and you can handle it matrix-wise just as you'd expect (always assuming
you have made sure it is a matrix, and not a jagged array).
Another thing to consider was raised in a comment by manu343726. Do you
want the code that receives this reference to vec[1] to be able to
use it to modify the contents of vec[1] - which would include changing its
size or the size of any of the vector<double>s within it?
If you allow modification, that's fine. If you don't then you want to get
a const reference. You can do that by:
vector<vector<double> > const & matrix = vec[1];
Possibly, you want the receiving code to be able to modify the doubles
but not the sizes of the vectors that contain them? In that case, std::vector
is the wrong container type for your application. If that's your position I
can update this answer to offer alternative containers.
Consider using matrix from some linear algebra library. There are some directions here
Having a bit of a headache trying to sum the elements in a 3d Vector.
Its for a k-means algorithm that I'm currently programming; an algorithm that I understand and can do on paper, but syntactically has me a bit tongue tied at the moment. I might mention that this project is the first time that I've really dealt with complex containers in C++. Currently I want calculate the new centroid for my points in a cluster, this is done by averaging the positions of every co-ordinate in the cluster. My 3d vector is set out as a vector of clusters each containing a vector which contain vectors of my co-ordinates in that cluster (I hope that sounds clear, hopefully my code will alleviate any confusion). I'm trying to use iterators at the moment, but am considering going back to ints and indices as I am more comfortable with them, though I feel that I should learn how this syntax works as it seems to be important and powerful.
I'll post just the function that I'm stuck on and the parts of the header that relate to it. If you would like to see any of the other code I'm happy to throw that in too on request, but I feel that this should be enough to show my problem.
.h file parts (public members of class):
vector< vector < vector <float> > > clusters;
vector<vector<float> > avg;
int avgDiv;
.cpp file part with comments to help elaborate my query:
vector<vector<vector<float> > >::iterator threeD;
vector<vector<float> >::iterator row;
vector<float>::iterator col;
for (threeD = clusters.begin(); threeD != clusters.end(); threeD++) {
for (row = threeD->begin(); row != threeD->end(); row++) {
for(col = row->begin(); col != row->end(); col++){
//its this code below that is causing my headache,
//I know that what is written isn't correct,
//it is there to serve as an example of what I've
//been trying to do to sort out my issue.
avg.at(row) ( = or push_back ) ((clusters.at(row).at(col)) + (clusters.at(row+1).at(col)));
}
avgDiv = distance(row->begin(),row->end());
//divide each value in avg vector by the amount of members in row, giving the new centroid for that cluster, loop forward to next cluster. this isn't a problem I should think.
}
}
My problem is that the compiler tells me that call to 'at' is not a member function. Now from what I can see from other questions it is because I'm not passing the right object as an arguement, though, I'm sure that I want to add together every element in the vector which the iterators are at together with the element next in the row.
I've tried and make this as clear as possible, please ask and I will add as much detail as I can to help you answer. I am new to this, and am very happy to take criticism; it will only make me a better programmer. Thank you for your time.
avg.at(index) is used with an integer index, it's just the 'c' array[index] notation with bounds checking - incidentally in real code you want to use [] or disable checking for speed.
But row is an iterator, effectively it's a pointer to the element in avg already so just dereference it to get the value.
*row = value of avg at position of iterator 'row'
A good tutorial on C++ iterators http://www.cprogramming.com/tutorial/stl/iterators.html
ps. With vectors and 'maths' type code, it's often simpler to just use array index notation