1

I am trying to write an efficient multistep solver in C++ using the Eigen library. To do so, I need a few variables that keep track of the history. One of them is of type Eigen::VectorX<Eigen::Matrix<double, 9, 10>> DD which is resized to 10000 somewhere in my initialization code.

Even though I know the size of DD at compile time, I need to allocate it on the heap because DD is too large for the stack (at least that's what Visual Studio 2022 tells me).

And here things are getting confusing to me. I'll try to explain why:

  1. You may have noticed that DD is a VectorX of size 10000 living on the heap. Its elements are of type Matrix<double, 9, 10>, hence living on the stack (?). Writing this text already sounds wrong to me. Is it possible to have an object that is allocated both on heap and stack? Or is the compiler moving everything on the heap?

  2. If allocating both on heap and stack is possible: does it influence the performance when reading from the DD?

  3. I thought I replace Matrix<double, 9, 10> by MatrixXd and give it a try. Well, it works but things are slown down by 15-20%. So, somehow I think this question gives an answer to my first and second question but I am really not convinced yet.

  4. If I could replace VectorX by Vector<..., 10000> would this increase performance? How could I "force" my program to use stack instead of heap?

  5. What other or better options do I have for DD to be defined? I replaced Eigen::Vector by std::vector which didn't really change anything, at least on performance side.

I need to read from DD all the time, so any help is highly appreciated.

4
  • 2
    "hence living on the stack (?)." No, it does not live on the stack the same way a std::vector<int> does not live on the stack even though an int does. And that having both the vector and the matrix dynamic adds overheads also makes sense as it means that the matrices don't lie on the heap in an orderly, consecutive fashion (in addition to allocation overheads). As this does not seem like a vector in the linear algebra sense (needing certain member functions / interfaces), I would go with the std::vector. Commented Feb 24 at 14:44
  • 2
    I think trying to force the whole vector of matrices on the stack is premature optimization, i.e. allocating a single big buffer in memory should not be the bottleneck of your solver. See also Is accessing data in the heap faster than from the stack?. Commented Feb 24 at 14:52
  • 1
    Depending on how they are used, it might make sense to add padding for the matrices to have a greater alignment. E.g. to avoid false sharing when different threads access different matrices in a parallel solver. Commented Feb 24 at 14:58
  • The only advantage of Eigen::VectorX<Eigen::Matrix<double, 9, 10>> vs std::vector<Eigen::Matrix<double, 9, 10>> is saving 8 bytes of stack memory. The actual data is stored on the heap in both cases. If you have a possibly dynamically growing or a large array of data of the same type (almost) always use std::vector (unless you have a good reason not to). Commented Feb 24 at 16:12

1 Answer 1

4

Memory is memory, your CPU has not concept of stack vs heap. The difference is that they are different data structures. Allocating on element on the stack is very cheap, you only have to increase the stack pointer. If you deallocate in the reverse order, this is also cheap, you just decrease the stack pointer. If you have many small allocations such as local variables in a function, the stack is a suitable data structure. For large working data, the allocation cost is negligible, and it is fine to allocate this on the heap.

  1. Eigen::VectorX<Eigen::Matrix<double, 9, 10>> points to a contiguous block of memory, so the elements of type Eigen::Matrix<double, 9, 10>> are located in a heap-allocated array. The matrices themselves are not separately allocated as you can compute the memory address from the index and the base pointer of DD.
  2. No
  3. There is some code needed to deal with dynamic sizes, and it also inhibits compiler optimisations. So a bit of slowdown is reasonable.
  4. Maybe, but I doubt it as the iteration over DD is in the outer-loop, so less critical to performance.
  5. I think the way you allocate it is ok.
Sign up to request clarification or add additional context in comments.

1 Comment

Ad 1) Technically, Eigen::VectorX<Eigen::Matrix<double, 9, 10>> itself is just a pointer and a size. But the pointer points to a contiguous block of memory. Ad 5) I would always default to std::vector here (until you have a good reason not to).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.