-
Notifications
You must be signed in to change notification settings - Fork 1.4k
[hist] Implement initial RHistEngine
#19732
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
base: master
Are you sure you want to change the base?
Conversation
Test Results 20 files 20 suites 3d 17h 24m 11s ⏱️ For more details on these failures, see this check. Results for commit 8928a0d. ♻️ This comment has been updated with latest results. |
Needed in the public interface of the histogram classes, so it should not be in the Internal namespace.
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.
Looks good! The below comments are mostly for the documentation or usability.
// We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might | ||
// be confusing for users. | ||
if (sizeof...(A) != GetNDimensions()) { | ||
throw std::invalid_argument("invalid number of arguments to Fill"); |
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.
Could one maybe format "<sizeof...(A)> vs <GetNDimensions>"
into the string to make exception::what()
more insightful, and also add the function name?
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 was worried that dynamic exception messages with std::string
could have a performance hit, and it seems to be the case when built with Clang:
RHistEngine_int_Regular1/Fill/4096 6645 ns 6637 ns 106185
RHistEngine_int_Regular2/Fill/4096 25946 ns 25915 ns 26760
goes to
RHistEngine_int_Regular1/Fill/4096 34293 ns 34253 ns 20438
RHistEngine_int_Regular2/Fill/4096 35925 ns 35883 ns 19754
GCC seems to be unaffected, maybe because of different code layout? I would like to investigate; if possible without performance hit, we can later on implement it consistently also for the exceptions in RAxes
.
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.
Right, so with dynamic std::string
concatenation neither Fill()
nore ComputeGlobalIndex()
are inlined anymore, which explains the performance penalty. It's possible to "fix" by making sure to outline the construction of the std::string
into a separate function:
std::string InvalidNumberOfArguments(std::size_t N) const
{
std::string msg = "invalid number of arguments to Fill: ";
msg += std::to_string(N) + " for " + std::to_string(GetNDimensions()) + " dimensions";
return msg;
}
throw std::invalid_argument(InvalidNumberOfArguments(sizeof...(A)));
This gives:
RHistEngine_int_Regular1/Fill/4096 6640 ns 6632 ns 106346
RHistEngine_int_Regular2/Fill/4096 25708 ns 25678 ns 27067
However I fear this depends on the compiler (version) and might change at any point. I think I would prefer to keep constant exception message strings for performance critical functions.
Fun fact, I first tried to outline ThrowInvalidNumberOfArguments
:
RHistEngine_int_Regular1/Fill/4096 18731 ns 18709 ns 37460
RHistEngine_int_Regular2/Fill/4096 30178 ns 30143 ns 23226
That's worse because the compiler cannot see throw
in that case; adding [[unlikely]]
brings it further down to:
RHistEngine_int_Regular1/Fill/4096 11911 ns 11897 ns 61084
RHistEngine_int_Regular2/Fill/4096 21541 ns 21516 ns 32604
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, let's leave it like that.
// RAxes::ComputeGlobalIndex will check the number of indices. | ||
RLinearizedIndex index = fAxes.ComputeGlobalIndex(indices); | ||
if (!index.fValid) { | ||
throw std::invalid_argument("bin not found"); |
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 one could make this a bit easier to trace by adding "RHistEngine::GetBinContent(): bin not found"?
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.
So far the other exception messages don't prefix the function name. I would argue that the stack trace should be used to find where the exception was thrown...
It combines an RAxes object and storage of bin contents.
This results in proper error messages when trying to stream. Other instantiations will be caught by the RAxes member.
It combines an
RAxes
object and storage of bin contents.