views:

132

answers:

3

I'm migrating some code from c to c++.

I've changed some malloc calls for structure memory allocation to new calls.

Basically before the code I'm porting was malloc'ing arrays that contain multiple sets of frame coords, each a couple hundred thousand floats in length -- so the total array length could be in the tens of millions of coordinates.

What kind of structure/container should I use?

And what kind of protections do I need to catch memory-related errors?


Edit 1
I've retitled/rephrased the question to more accurately reflect what I'm trying to do.

I'm think some sort of 2D list-like structure might do the trick... possibly a std::deque of std::deque(s)?

+1  A: 

When allocating through new fails it throws std::bad_alloc. But do you really requite so many floats in continuos memory location. If not you can take a look at other datastructures such as std::deque or std::list

EDIT: list doesn't make sense as you are asking for a replacement for an array.

Naveen
Please please not `list`.
Billy ONeal
hmm yea thats probably a good thought. Which would be best a deque, a vector, or a list?? I ask because, all would seemingly work, because basically I'm just assigning storing and testing values. I will be access all through the series of values later in my program, not just at the ends.
Jason R. Mick
@Naveen -- and can those structures throw bad_alloc's too? I've worked with vectors before, but never something this long...
Jason R. Mick
@Bill ONeal: Any particular reason? For performance reason in case of random access?
Naveen
@Jason: `vector` will not help as it stores the elements in continuous memory location. Which data structure to use would depend upon the type of operations being used.
Naveen
An array of 200,000 floats is probably less than a megabyte. Maybe he's on a platform where that would be considered lot of memory, but for the average application on the average computer, that's not a big deal. If use of `malloc` in the C version of the code didn't lead to memory-usage issues, then it shouldn't be a problem in C++ either. (FWIW, I'd probably use a `vector` rather than a raw array, just to avoid dealing with `new` and `delete`.)
Kristopher Johnson
@Jason - which data structure to use depends on how you want to use it. If you want something analogous to an array in most aspects a vector is the best. And it handles the memory allocation/deallocation for you. It doesn't catch exceptions however, so it will throw bad_alloc.
Niki Yoshiuchi
Whoops, I lied. Its 100k-200k elements, but those are over multiple frames -- possibly hundreds. So you're looking at tens of millions of floats. A two dimensional accessible list would be preferred. Can I utilize a deque of deques?
Jason R. Mick
...see my edits for the modified question.
Jason R. Mick
@Naveen: Because memory usage for a list of floats is **at least** 3 times as high as a dumb array. (2 pointers for next/prev, both of which are at least once but maybe twice the size of a float, not to mention the typical 16 bytes of overhead for an allocation imposed by the memory manager) Not to mention `list` throws cache locality out the window. In 99% of cases, `std::deque` offers most of `list`'s advantages with few of it's drawbacks.
Billy ONeal
@Billy can you answer my revised question? for example if i have 150,000 points and 400 frames, can I say std::deque<std::deque<float>> x_coords; ...and then access with say x[129000][30]; //particle 129,000, frame 30.
Jason R. Mick
@Jason: I really don't understand the question. If you're asking if that should work, then I see no reason why it would not.
Billy ONeal
@Billy: My question is: What is the best/safest way to allocate/contain that many floats? It seems like a deque of deques is the best approach? Would you agree, and if not, why?
Jason R. Mick
@Jason - a vector of vectors or a deque of deque. If you are afraid of allocating large contiguous blocks of memory then a deque of deques.
Niki Yoshiuchi
+1  A: 

EDIT: If you want a C++ style matrix then I would first recommend boost::matrix:

boost::matrix<float> my_matrix(n, m);

If you can't use boost, then I would recommend a vector of vectors.

std::vector<std::vector<float> > m_matrix(n, std::vector<float>(m));

(notice the space after the first >, this is necessary because >> is an operator in C++).

You can also use a deque of deques (or a combination of vectors and deques). The big difference is that vectors guarantee that the elements are stored in a contiguous block of memory where a deque does not. This may or may not be a good thing for your purposes.

Deques are also more efficient at insert new elements in the middle of the structure.

Yes, a call to new can fail. Generally if a call to new fails it throws a std::bad_alloc exception, which you can catch. Since you are migrating code from c to c++, it might be easier to use std::nothrow, which will cause new to return a null pointer (much like malloc).

try
{
  my_array = new float[num_points];
}
catch(std::bad_alloc &exp)
{
  ...
}

or

my_array = new (std::nothrow) float[num_points];
if(m_array == NULL)
{
  ...
}
Niki Yoshiuchi
Just to be clear, a vector of vectors, std::vector<std::vector<float> >, does not store all the elements in contiguous locations. In particular, the rows (the floats in the inner vectors) will be contiguous, but they are allocated independently from each-other. The outer vector stores a contiguous array of std::vector objects which only contain pointers to the row data.
antonm
+1  A: 

Answer is std::vector.

You don't need that much memory actually (or you have some memory constrained platform, I assume you would have told us in that case). Vector is perfectly fine for this purpose. And you don't have to manage the memory yourself.

You can use vectors of vectors if you want to manage several of them at once.

But some 10^6s floats is definitely not a big deal nowadays.

Update: One more thing if you go with deque. Please don't access deque objects by index in loops. Actually deque is strong at inserting at both sides, but not at accessing objects by index. And probably not at inserting objects in the middle, as I have seen somehere.

Alexandre C.
10^6 floats isn't that much memory these days but it's still a lot of memory to have in one contiguous block. He also stated that he might need several hundred of these. If the memory is at all fragmented you could quickly run into trouble.
Niki Yoshiuchi
Memory fragmentation is not an issue at all if the blocks are requested once and not freed often, which I assume here (@OP: feel free to provide information about this). Memory fragmentation is a big deal whenever you move stuff around often.
Alexandre C.
So if I understand correctly, if I have a 50 MB list of floats and save it as a deque the performance will be poor, but if I HAVE to save it as a deque or I may run into memory errors, correct? Is there any good solution to this dilemma?
Jason R. Mick
a 50Mb list of floats is a perfect candidate for a vector. Deque slices the memory in parts to make it efficient to insert into the structure. If you don't need inserting, use vector. Error handling is made in C++ through exceptions, as pointed out in the commentaries of your question. But if I were you, I wouldn't worry too much about it.
Alexandre C.