Prealloc memory list - c++

We try to develop a realtime application. In this program 4 cameras send 100 times a second there image array to a method.
In this method I have to make copy of each array. (Used for ImageProcessing in other thread).
I would like to store the last 100 images of each camera in a list.
The problem is: How to prealloc such memory in list (new them in constructor?).
I would like to use something like a ringbuffer with fixed size, allocated memories array and fifo principal.
Any idea how?
Edit1:
Example pseudo code:
// called from writer thread
void receiveImage(const char *data, int length)
{
Image *image = images.nextStorage();
std::copy(data, data + length, image->data);
}
// prealloc
void preallocImages()
{
for (int i = 0; i < 100; i++)
images.preAlloc(new Image(400, 400));
}
// consumer thread
void imageProcessing()
{
Image image = image.WaitAndGetImage();
// ... todo
}

Say you create an Image class to hold the data for an image, having a ring buffer amounts to something like:
std::vector<Image> images(100);
int next = 0;
...
while (whatever)
{
images[next++] = get_image();
next %= images.size();
}
You talk about preallocating memory: each Image constructor can own the task of preallocating memory for its own image. If could do that with new, or if you have fixed-size images that aren't particularly huge you could try a corrspondingly sized array in the Image class... that way the all image data will be kept contiguously in memory - it might be a little faster to iterate images "in order". Note that simply having allocated virtual addresses doesn't mean there's physical backing memory yet, and that stuff may still be swapped out into virtual memory. If you have memory access speed issues, you might want to think about scanning over the memory for an image you expect to use shortly before using it or using OS functions to advise the OS of your intended memory use patterns. Might as well get something working and profile it first ;-).
For FIFO handling - just have another variable also starting at 0, if it's != next then you can "process" the image at that index in the vector, then increment the variable until it catches up with next.

Related

C++ bad_alloc error after running code successfully multiple times

I am relatively new to C++ and I've having an issue with my project.
I ran the following code a few times without a problem, but now when I try to run it it gives me a std::bad_alloc error. The code is C++ but some lines are exclusive to ROOT which is program written in C++ for particle physicists.
class Particle {
public:
int pdgid;
float px;
Particle(int pdg, float px){
pdgid = pdg;
px = px;
}
};
TFile* file = new TFile("filename.root"); //ROOT code, where particle values are obtained from.
TTree* tree = (TTree*)file->Get("FlatTree"); //tree is where all events and associated values are held
vector<Particle> allparticles;
for (unsigned iEntry = 0; iEntry<tree->GetEntries(); iEntry++) {
tree->GetEntry(iEntry);
for (int iVecEntry = 0; iVecEntry < nfsp; iVecEntry++) {
allparticles.push_back(Particle(pdg[iVecEntry],px[iVecEntry]));
}
}
The code works if I decrease the limit of the first for loop. The number of entries is quite large (over 2 million) and nfsp can be up to 24 depending on the event. This resulted in the vector allparticles having over 7 million Particle objects.
I think the problem lies with not having enough memory to allocate such a large vector but how was this working previously? Is it possible that the memory wasn't deallocated properly the first few times I ran the code?
I a bit confused about memory management. In C++ does the OS handle deallocation? Or do I have to include a destructor?
I have tried including a destructor but could not get it to work.
From "std::bad_alloc": am I using too much memory? I tried including a delete[] statement at the end of the code but this also doesn't work.
Any input and help is much appreciated!
P.S. I'm running linux mint 18.2 Sonya.
Yes, it sounds like you have run out of stack memory. Here is one of the many tutorials out there that explain heap vs stack memory.
You are creating your particles in stack memory, so this means that they will be automatically destroyed when they go out of scope. You stack memory size varies depending on the compiler and environment, but you get way less stack memory than heap memory.
To fix this, I would create a vector of pointers to Particles, and create the Particles dynamically. Example:
vector<Particle*> allparticles;
...
allparticles.push_back(new Particle(pdg[iVecEntry],px[iVecEntry]));
Remember, to delete the dynamically allocated heap memory when you are done with it. Example:
for(int i < 0; i < allparticles.size(); i++){
delete allparticles[i];
}

Array pointer data being cleared in between function calls without an explicit command?

I have the following issue:
In a C++ program I have a global data structure declared as Renderer Rendering_Handler, which contains a member field defined as vector<Render_Info> visble objects.
What the data structures themselves are doing is not important, they are wrappers needed to abstract data to parallelize my program.
To be clear, Rendering_Handler is completely global, and it's in fact a singleton (I can 100% confirm that the constructor has been called once and only once for this class).
I have declared the following class method:
Render_Info* Renderer::add_Render_Info()
{
visible_objects.push_back(Render_Info());
return &(visible_objects.back());
}
Simple enough, it creates a new Render_Info structure, appends it to the visible_objects array and returns a pointer to the object.
A different data structure called Chunk has a constructor defined as
Chunk::Chunk(vec3 offset, World* w)
{
/*initialize some values*/
draw_info = Rendering_Handler->add_Render_Info();
draw_info->VBOs = vector<GLuint>(5);
/*initialize OpenGL VAOs, VBOs and other buffer objects*/
cout << draw_info->VBOs.size() << endl;
cout << draw_info << endl;
}
It also has a method defined as:
void Chunk::update_render_info()
{
cout << draw_info->VBOs.size() << endl;
cout << draw_info << endl;
/*OpenGL stuff*/
}
And finally
We have the method that initializes everything:
World::World()
{
/*Initialize chunks in a circular 3D array*/
loaded_chunks = new Chunk_Holder(h_radius, h_radius, v_radius, this);
for(int i=0; i<h_radius; i++)
{
for(int j=0; j<h_radius; j++)
{
for(int k=0; k<v_radius; k++)
{
(*loaded_chunks)(i,j,k)->update();
}
}
}
}
The output of the rpgram is:
...
Let's focus on the frist 2 and last 2 lines of the output, which correspond to the print statements I have added for debugging.
The first 2 lines indicate that 5 elements have been added to the buffer at location 0x556edb7ae200
The last 2 lines tell me that the same buffer (same since the memory location is the same) now contains 0 elements.
As you can see from the snaps of the code, no function is called in between creating the Chunks and updating them. Does anybody have an idea of what could be causing the dissapearance of these elements?
Have I not correctly reserved the memory? Are these objects being cleared without my knowledge due to wrong allocation?
I think the problem is that you're storing pointers to elements in vector and at the same time you keep calling vector::push_back which every now and then has to resize the vector and move all elements to new memory chunk. This will invalidate all the pointers you have obtained before.
To give you more context: vector stores its elements in a continuous chunk of memory. When vector::push_back is called and there's no free space left in this chunk of memory then vector will allocate another chunk of memory with twice the size of the old chunk. Then it will copy/move all the elements from old chunk to the new one. Finally the old chunk will be destroyed. When you call &(visible_objects.back()) you will get an address in memory that's inside current memory chunk owned by visible_objects. If later visible_objects.push_back is called and visible_objects has to migrate to new bigger memory chunk then all the addresses obtained before will be stale as they point to the old chunk of memory that has been destroyed.

std::vector resize(0) or clear() - but keep it's capacity

I'm merging many objects into a single vector containing render data (a mesh). This vector gets cleared and refilled on each frame (well, almost).
The issue is that clearing and then again reserving the vector size has a huge impact on performance in my case, because clear() may also change the capacity.
In other words, I need to control when the capacity of the vector gets changed. I want to keep the old capacity for quite some time, until I decide myself that it's time to change it.
I see two options:
Figure out how to control when the capacity of std::vector is about to change
Implement a memory pool for large memory objects which will fetch a large data object of <= required size and reuse / release it as I need.
Update
In addition, what if for example a resize(10), and later a resize(5) was called (just for illustration, multiply actual numbers by some millions)?
Will the later call to resize(5) cause the vector to, maybe, reallocate?
Actually the clear member function keeps the vector capacity unchanged. It only destroys (calls the destructor) each of the vector elements and sets the vector size to 0.
In this situation, at each iteration, I would call clear() to destroy all the vector elements, then call the member function reserve(size) which, in the case where the vector capacity is too small, will increase it to at least size.
This vector gets cleared and refilled on each frame (well, almost).
I would recommend a different approach.
Create a class that acts as a buffer for the rendering data.
If I am not mistaken, you never reduce the capacity of the buffer. You only increase its capacity when needed.
Make sure that class is an implementation detail and only instance is ever constructed.
Here's a skeletal implementation of what I am thinking.
namespace Impl_Detail
{
struct Buffer
{
size_t capacity;
size_t size;
std::vector<char> data;
// Pick whatever default capacity makes sense for your need.
Buffer(size_t cap = 100) : capacity_(cap), size_(0), data(cap) {}
void ensureCapacity(size_t cap)
{
if ( capacity_ < cap )
{
capacity_ = cap;
data.resize(capacity_);
}
}
// Add any other helpful member functions as needed.
};
// Create an instance and use it in the implementation.
Buffer theBuffer;
}

Storing unused class data members on disk

I have a GUI application which works with point cloud data and a quadtree data structure behind it to handle the data. As the point format I'm working with has changed recently I had to modify my point class to hold the new attributes, which cause Point objects to grow in size significantly and in effect reducing the performance of my quadtree. Some of this attributes are not needed for displaying and processing the data, but they still need to be preserved in the output. This is roughly how my point class looks at the moment:
class Point {
public:
/* ... */
private:
/* Used data members */
double x;
double y;
double z;
double time;
int attr1;
int attr2;
/* Unused data members */
int atr3;
double atr4;
float atr5;
float atr6;
float atr7;
}
When the data is loaded from the file the Points are stored in a Point* array and then handled by the quadtree. Similarly when they are savedan array of points is passed from the quadtree and saved to a file. Note that Point objects I'm using in my quadtree are different fomr those stored in the file, but I'm using a library that provides reader and writer objects which I use to create my points. Here's an example:
int PointLoader::load(int n, Point* points) {
Point temp;
int pointCounter = 0;
/* reader object is provided by the library and declared elsewhere */
while (pointCounter < n && reader->read_point()) {
temp = Point(reader->get_x(), reader->get_y(), reader->get_z(), /* ... */ )
points[pointCounter] = temp;
++pointCounter;
}
return pointCounter;
}
Now, my idea is to reduce size of the Point class, and store unused attributes in another class (or struct) called PointData on the hard drive. This is necessary because the data usually doesn't fit in memory and there's a caching system in place, which again would benefit from smaller point objects. So given the example it would look something like this:
int PointLoader::load(int n, Point* points) {
Point temp;
PointData tempData;
int pointCounter = 0;
while (pointCounter < n && reader->read_point()) {
temp = Point(reader->get_x(), reader->get_y(), reader->get_z(), /* ... */ )
pointData = (reader->get_attr3(), reader->get_attr4(), /* ... */)
temp.dataHandle = /* some kind of handle to the data object */
points[pointCounter] = temp;
/* Save pointData to file to retrieve when saving points */
++pointCounter;
}
return pointCounter;
}
Then when I save my modified points I'd simply used the dataHandle (file offset? an index in memory mapped array?) to retrieve the pointData of each point and write it back to the file.
Does that sound like a good idea? What would be the most sensible approach of achieving this?
I would suggest you use mapped files for storing the additional data. This will automatically cause them to be flushed to disk and removed from RAM if there is memory pressure, but they will stay resident in RAM most of the time if there is enough memory.
In your Point class, storing offsets in the file is better than storing direct pointers into the mapped memory region as offsets will still be correct if you have to remap the file in order to grow it (you have to grow the file using e.g. lseek() yourself, as you can only map as much as the size of the file).
This mechanism is very convenient to code to, but you must have enough address space to map the whole file - no issue in a 64-bit app, but possibly a problem if you're 32-bit and need more than a few hundred MB of data in the file. You can of course map and unmap multiple files, but it requires more coding work and is less performant (there is some cost to mapping and unmapping files).

What's the proper way to declare and initialize a (large) two dimensional object array in c++?

I need to create a large two dimensional array of objects. I've read some related questions on this site and others regarding multi_array, matrix, vector, etc, but haven't been able to put it together. If you recommend using one of those, please go ahead and translate the code below.
Some considerations:
The array is somewhat large (1300 x 1372).
I might be working with more than one of these at a time.
I'll have to pass it to a function at some point.
Speed is a large factor.
The two approaches that I thought of were:
Pixel pixelArray[1300][1372];
for(int i=0; i<1300; i++) {
for(int j=0; j<1372; j++) {
pixelArray[i][j].setOn(true);
...
}
}
and
Pixel* pixelArray[1300][1372];
for(int i=0; i<1300; i++) {
for(int j=0; j<1372; j++) {
pixelArray[i][j] = new Pixel();
pixelArray[i][j]->setOn(true);
...
}
}
What's the right approach/syntax here?
Edit:
Several answers have assumed Pixel is small - I left out details about Pixel for convenience, but it's not small/trivial. It has ~20 data members and ~16 member functions.
Your first approach allocates everything on stack, which is otherwise fine, but leads to stack overflow when you try to allocate too much stack. The limit is usually around 8 megabytes on modern OSes, so that allocating arrays of 1300 * 1372 elements on stack is not an option.
Your second approach allocates 1300 * 1372 elements on heap, which is a tremendous load for the allocator, which holds multiple linked lists to chunks of allocted and free memory. Also a bad idea, especially since Pixel seems to be rather small.
What I would do is this:
Pixel* pixelArray = new Pixel[1300 * 1372];
for(int i=0; i<1300; i++) {
for(int j=0; j<1372; j++) {
pixelArray[i * 1372 + j].setOn(true);
...
}
}
This way you allocate one large chunk of memory on heap. Stack is happy and so is the heap allocator.
If you want to pass it to a function, I'd vote against using simple arrays. Consider:
void doWork(Pixel array[][]);
This does not contain any size information. You could pass the size info via separate arguments, but I'd rather use something like std::vector<Pixel>. Of course, this requires that you define an addressing convention (row-major or column-major).
An alternative is std::vector<std::vector<Pixel> >, where each level of vectors is one array dimension. Advantage: The double subscript like in pixelArray[x][y] works, but the creation of such a structure is tedious, copying is more expensive because it happens per contained vector instance instead of with a simple memcpy, and the vectors contained in the top-level vector must not necessarily have the same size.
These are basically your options using the Standard Library. The right solution would be something like std::vector with two dimensions. Numerical libraries and image manipulation libraries come to mind, but matrix and image classes are most likely limited to primitive data types in their elements.
EDIT: Forgot to make it clear that everything above is only arguments. In the end, your personal taste and the context will have to be taken into account. If you're on your own in the project, vector plus defined and documented addressing convention should be good enough. But if you're in a team, and it's likely that someone will disregard the documented convention, the cascaded vector-in-vector structure is probably better because the tedious parts can be implemented by helper functions.
I'm not sure how complicated your Pixel data type is, but maybe something like this will work for you?:
std::fill(array, array+100, 42); // sets every value in the array to 42
Reference:
Initialization of a normal array with one default value
Check out Boost's Generic Image Library.
gray8_image_t pixelArray;
pixelArray.recreate(1300,1372);
for(gray8_image_t::iterator pIt = pixelArray.begin(); pIt != pixelArray.end(); pIt++) {
*pIt = 1;
}
My personal peference would be to use std::vector
typedef std::vector<Pixel> PixelRow;
typedef std::vector<PixelRow> PixelMatrix;
PixelMatrix pixelArray(1300, PixelRow(1372, Pixel(true)));
// ^^^^ ^^^^ ^^^^^^^^^^^
// Size 1 Size 2 default Value
While I wouldn't necessarily make this a struct, this demonstrates how I would approach storing and accessing the data. If Pixel is rather large, you may want to use a std::deque instead.
struct Pixel2D {
Pixel2D (size_t rsz_, size_t csz_) : data(rsz_*csz_), rsz(rsz_), csz(csz_) {
for (size_t r = 0; r < rsz; r++)
for (size_t c = 0; c < csz; c++)
at(r, c).setOn(true);
}
Pixel &at(size_t row, size_t col) {return data.at(row*csz+col);}
std::vector<Pixel> data;
size_t rsz;
size_t csz;
};