• Advertisement
Sign in to follow this  

Using malloc and memcopy in C++

This topic is 3329 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Advertisement
For POD types, it has the same semantics as in C.

But there is no real reason to use malloc for PODs. There's also std::copy portable version of memcpy (which usually delegates to memcpy).

Share this post


Link to post
Share on other sites
It's *OK-ish* with POD (http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.7) but there are some gotchas. You should use "new" instead of malloc. std::copy is also a safer alternative to memcpy in many cases.

This is a general reply to your general question. Things could get more specific though.

Share this post


Link to post
Share on other sites
Well, I have a 2D vector class, and a polygon class that has an array of that vector class. The polygon class gets copied around alot during the calculations, so I figured that to speed things up, I can used memcopy to copy the vector array instead of looping through it. My vector class is a class, but there is nothing stopping me from making it a struct. Also, the only critique in the POD definition that my vector class doesn't mach is having a constructor, but I only use the constructor to set the x and y values, so I don't think it should be such a problem...

Share this post


Link to post
Share on other sites
It sounds like you think using memcpy and malloc is going to be faster than new and std::copy. But for equivalent correct uses of either the performance will also be equivalent. It's not worth stripping functionality from your class just so you can safely memcpy and malloc instances of it.

Have you actually determined that copying the array of vectors during the copy operation for your polygon is a bottleneck? Have you considered alternative algorithmic solutions to avoid the copy overhead?

Share this post


Link to post
Share on other sites
If you have a lot of copying, make a reasonable effort to reduce it as much as possible. After you have done that, make sure your data is properly aligned and properly sized for all optimizations malloc/std::copy provide (mainly, using SIMD instructions) For larege arrays, this should definitely be faster than looping through manually.

Using malloc should not give you a performance boost over new.

Having a constructor yet being ok for you array to be allocated with malloc si a proff of a conceptual problem. Either you don't need a constructor and you will handle initializing stuff yourself, or you do need a constructor and you are going to have some problems because it won't be called.

Last point, struct differ from class as all members are public by default in a struct. Nothing else. Correct me if I'm wrong but you seem to think otherwise.

Share this post


Link to post
Share on other sites
Quote:
Original post by someboddy

The polygon class gets copied around alot during the calculations, so I figured that to speed things up, I can used memcopy to copy the vector array instead of looping through it.


mempcy will be probably faster by a few fractions.

Reducing number of copies however will be faster by a factor.

If you're copying between states, then consider changing your algorithms so they operate on two buffers. So instead of copying the array, then modifying values in place, perform the operation from old array into new.

Share this post


Link to post
Share on other sites
std::vector is smart enough to detect when you use a pod type and then internally use std::copy, which in turns uses memcpy.

The difference is that your code will look much cleaner than if you use malloc/memcpy manually.

Share this post


Link to post
Share on other sites
std::vector probably always uses std::copy internally, which if the type has "trivial assignment" and the iterators are random access might be implemented in terms of memmove (at least in MinGW). However do the compilers realize that the assignment is indeed trivial for user-defined types?

Not saying that reducing the copying itself rather than optimizing the method of copying is a better answer, I don't have infinite trust in compilers and STL implementations. For example, recently I discovered that std::iter_swap in MinGW 3.4.5 is not implemented in terms of swap, meaning that none of the std algorithms in this implementation take advantage of overloaded efficient swap methods (e.g for types such as std::string).

Share this post


Link to post
Share on other sites
I did check the current gcc implementation. It uses the tr1 is_pod type trait to determine if the type is a pod, and if it is uses __uninitialized_copy, which in turns I seem to recall was using std::copy but I may have had that bit wrong. The code's a bit difficult to follow. But it did end up with a plain memory copy.

Yeah, some older implementations of the stl might be subpar, but it's hardly something to worry about when proper implementations are as easily available.

I'd rather have my code run sub-optimally on some compilers than uglify it with premature optimizations that will be irrelevant in a few years when people stop using old compilers.

Share this post


Link to post
Share on other sites
So classes can be treated as POD by the compiler? That's good to hear.

Actually, I don't have any slowdowns currently, since my game is still at tech demo stage. I've just figured out that all those coping around could be a slowdown. And most of them are necessary...

Share this post


Link to post
Share on other sites
Quote:
Original post by someboddy

I've just figured out that all those coping around could be a slowdown.


If only there existed some way to know for sure. Like a tool. That would profile time spent in various parts of code.

Share this post


Link to post
Share on other sites
Quote:
Original post by someboddy
Well, I have a 2D vector class, and a polygon class that has an array of that vector class. The polygon class gets copied around alot during the calculations, so I figured that to speed things up, I can {do more work, and I don't know yet if it will make a difference}


Now, hold on. Who's in charge here, you, or the computer? Whose time is more valuable?

Quote:
My vector class is a class, but there is nothing stopping me from making it a struct.


There is no difference in C++ between 'struct's and 'class'es, beyond the defaults for public/private member (and base) access.

Further, there is no reason that using any of memcopy, malloc, std::copy, new, etc. etc. etc. would require structs rather than classes, or vice-versa. Class instances can be POD.

Quote:
Also, the only critique in the POD definition that my vector class doesn't mach is having a constructor, but I only use the constructor to set the x and y values, so I don't think it should be such a problem...


Practically, it will probably work, but the Standard says it's not guaranteed to work. I can write a compiler that would take your code and end up horribly mangling things at runtime, and the people who define the language would defend me.

Optimization at this level is for specialized experts (such as "our own" Jan Wassenburg), and for the people who provide the compiler. If there were really any way you could make this faster, there would be huge numbers of people interested in it, and thus you could easily have a high-paying job helping develop the next version of VC++ or whatever.

The short version is, there's no reason for any normal developer not to use std::copy for range-copying, std::fill for range-initialization, and std::vector for array-memory-management in C++.

Share this post


Link to post
Share on other sites
OK, so you all think I should leave those kind of optimizations to the compiler. but how does the compiler knows if a class is POD? The constructor is there for convenience, it doesn't initialize anything vital(ofcourse, not having rubbish data is quite vital, but you know what I mean...), but will the compiler realize this and treat it as a POD, or does it have a thumb rule - contructor==not POD? Is there a way to define to the compiler that a certain class is POD?

I tried to use the "is_pod" class to check if my vector class is POD, but it seems like I don't have the "type_traits" header. Where can I get that library?

Share this post


Link to post
Share on other sites
Quote:
Original post by someboddy
OK, so you all think I should leave those kind of optimizations to the compiler. but how does the compiler knows if a class is POD? The constructor is there for convenience, it doesn't initialize anything vital(ofcourse, not having rubbish data is quite vital, but you know what I mean...), but will the compiler realize this and treat it as a POD, or does it have a thumb rule - contructor==not POD? Is there a way to define to the compiler that a certain class is POD?


There are precise rules in the standard as to what is a POD:
http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html

Constructors are unfortunately not allowed.

I had checked earlier and thought trivial constructors were allowed, but I only have a copy of the draft c++0x standard handy and it turns out they are relaxing the rules for PODs:
c++0x: http://en.wikipedia.org/wiki/C++0x#Modification_to_the_definition_of_plain_old_data

Quote:
I tried to use the "is_pod" class to check if my vector class is POD, but it seems like I don't have the "type_traits" header. Where can I get that library?


#include <type_traits> would only work with a c++0x compiler (in c++0x mode). But you can try #include <tr1/type_traits> (then access it in the tr1 namespace).

Alternatively boost have an implementation of that.

Share this post


Link to post
Share on other sites
I highly recommend downloading the Loki library and trying out yasli_vector (stands for "Yet Another Standard Library Implementation"). It detects POD types and uses memcpy for those, and there is even a way of telling it that your structs are POD so that it can do it for those too. I think you could even define move constructors for your class and have it take advantage of those too if memory serves me well.
Either way, it's got some way cool stuff!

Share this post


Link to post
Share on other sites
Quote:

Alternatively boost have an implementation of that.


It seems to me that boost only detects built-in types as POD (with MinGW 3.4.5)

I did find a "type_traits.h" file that is used internally, and it contains a struct like this with specializations for built-in types and pointers.


struct __type_traits
{
typedef __true_type this_dummy_member_must_be_first;
typedef __false_type has_trivial_default_constructor;
typedef __false_type has_trivial_copy_constructor;
typedef __false_type has_trivial_assignment_operator;
typedef __false_type has_trivial_destructor;
typedef __false_type is_POD_type;
};




Now you could provide an specialization for your type, but that would be non-portable and fragile (the type might be changed so that the typedefs in the specialization don't hold).

I don't see how it is possible to implement is_pod (or typetraits generally) purely as a library. As I understand the compiler must help and automatically generate a specialization for your types using knowledge about the type that isn't available at code level.

Share this post


Link to post
Share on other sites
Quote:
Original post by visitor
It seems to me that boost only detects built-in types as POD (with MinGW 3.4.5)


Boost type traits such as is_pod will use compiler intrinsic support where available, VC++ 8.0 above has intrinsic support and if i remember correctly so does GCC for quite sometime.

If your compiler doesn't have intrinsic support for is_pod then you're are suppose to (partially) specialize your user-defined types to state that they are POD-struct types.

Share this post


Link to post
Share on other sites
Quote:
Original post by snk_kid

If your compiler doesn't have intrinsic support for is_pod then you're are suppose to (partially) specialize your user-defined types to state that they are POD-struct types.


How can I do that?

Share this post


Link to post
Share on other sites
Quote:
Original post by someboddy
Quote:
Original post by snk_kid

If your compiler doesn't have intrinsic support for is_pod then you're are suppose to (partially) specialize your user-defined types to state that they are POD-struct types.


How can I do that?


Just (partially) specialize boost::is_pod:


#include <boost/static_assert.hpp>
#include <boost/type_traits/is_pod.hpp>

struct my_pod_type {};

template <>
struct boost::is_pod<my_pod_type> : boost::true_type {};

BOOST_STATIC_ASSERT((boost::is_pod<my_pod_type>::value));


There most probably is a macro to help write specialization boiler-plate code, just check the documentation.

Share this post


Link to post
Share on other sites
You can do that but then... are you going to reimplement STL to use boost::type_traits?

Just write normal code and then see if the program is reasonably fast and what are the bottle-necks if any.

Share this post


Link to post
Share on other sites
Quote:
Original post by visitor
You can do that but then... are you going to reimplement STL to use boost::type_traits?

Just write normal code and then see if the program is reasonably fast and what are the bottle-necks if any.


I haven't read the entire thread so I don't know what you're talking about, standard library containers & algorithms are not typically based off of boost's type traits.

Besides, as I said already most modern compilers have compiler intrinsic support for type traits and use it for their library implementations so you don't need to worry about having to explicitly specialize code. Furthermore iterator categories are also used to specialize generic code to.

So if a compiler doesn't have intrinsic support they will still use iterator categories to use the most optimal implementation for example loops with random accessible iterators can be written to be more amenable to loop unrolling, as opposed to the generic itr != end pattern.

[Edited by - snk_kid on January 13, 2009 12:43:22 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement