-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ML] Decrease the memory used by distribution models #146
[ML] Decrease the memory used by distribution models #146
Conversation
…on't need precision). Make enums 32 bits
include/maths/MathsTypes.h
Outdated
@@ -42,7 +42,12 @@ using TCalendarComponentVec = std::vector<maths::CCalendarComponent>; | |||
//! -# ContinuousData: which indicates the takes real values. | |||
//! -# MixedData: which indicates the data can be decomposed into | |||
//! some combination of the other three data types. | |||
enum EDataType { E_DiscreteData, E_IntegerData, E_ContinuousData, E_MixedData }; | |||
enum EDataType : std::int32_t { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this actually making a difference on any platform? On all the platforms we support int
is 32 bits. And I know gcc
uses int
for enum
s unless it's forced to do something different.
The C++ standard says that compilers can choose any integral type that can accommodate all the enum
values to represent the enum
type. But in practice they'll probably favour int
as the C standard says the enum
values must be int
, and it would be foolish for a compiler vendor to introduce an incompatibility in the binary output for the same header file depending on whether it was compiled as C or C++.
So does clang
or Visual C++ use a different enum
size by default? If not, I think this is just introducing a distraction into the code without changing the end result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok good point. I'd actually switched them to int8_t originally, but it caused knock on problems for printing them out which created more code churn. I'll double check and revert if it doesn't make a difference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other problem: Even if you force shrink the datatype like this (I agree int should be 32bit also on 64bit) you might not achieve the desired affect due to padding in the class instances where that is used.
(Do we correctly take padding into account in the memory usage calculations?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also shuffled some variable orders around so we would've benefited from shrinking these. I'm just doing a run now though to verify if we do actually get anything from this, I suspect Dave is right though and we don't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, we're using sizeof to get the size of these classes in the memory calculation (which include pads).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Do we correctly take padding into account in the memory usage calculations?)
We take padding between members of a single object into account, because we use sizeof(obj)
rather than sizeof(member1) + sizeof(member2) + ...
.
What we don't take into account is allocator overhead. For example, if we ask for a 27 byte chunk of memory and the OS gives us a 32 byte chunk instead then we'll count 27 if sizeof(obj)
is 27. And nor do we take into account any allocator data structures like pointers to the next block in a free list.
But model memory is only meant to be a rough estimate - getting it absolutely perfect would be incredibly hard and would involve having a very deep knowledge of what malloc()
is doing on each platform.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Maybe there are data structures which would benefit from disabling padding? If so we could try and see what are the savings in memory and what is the added runtime (hopefully not that bad).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's an interesting suggestion. I reordered variables in this change, so it should be able pack the types properly, but there may be other cases. Maybe something to look into down the line. The only slight caveat is it has been worthwhile shrinking these because of the upcoming change to model multi-bucket features will duplicate them per time series model. I suspect we may have smaller wins elsewhere.
d0050a4
to
de3f364
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit late to the party but LGTM
This makes some type changes to reduce precision of quantities where we don't need that precision. For example, this saves us around 15% of the memory typically used by the count residual distribution model (dropping from 1900 to 1650 bytes).
This may have a small affect on results simply due to slightly different rounding of floating point quantities.