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
Use openMP to parallelize TOF calibration #6568
Conversation
72cd5fd
to
900bf5b
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.
without checking in detail, looks ok, just one question below
|
||
#ifdef WITH_OPENMP | ||
if (mNThreads < 1) { | ||
mNThreads = std::min(omp_get_max_threads(), NMAXTHREADS); |
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.
how many sectors does TOF have? Is it really 20?
Since you parallelize over the sectors, I think it would make sense to set NMAXTHREADS to the number of tof sectors?
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.
They are 18. The 20 is the number that I got on my desktop. I can change it to 18, sure.
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.
If you want to impose a limit, I would put nSectors, 20 doesn't make sense since with parallelization over the sectors you cannot run 20 threads.
But in principle you also do not need to impose a limit
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.
Yes, you are right, only 18 threads will be created at max in any case. 20 was just the limit I had on my desktop, so what omp_get_max_threads()
was returning. Then I thought that if you have something else running, this number will be less, so I used the minimum between the two. But if this is exactly what is done automatically, then I would remove this setting.
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, now I checked the code. Here the logic is: if you don't set the number of threads from outside, then you want that it parallelize as much as it can. If I just put:
mNThreads = omp_get_max_threads();
I guess it will know that the max is 18 from the fact that we parallelize the loop over the 18 sectors, right?
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.
Hi,
I've added a lot of comments some 10 days age, but forgot to submit them, sorry.
Apart from the technical comments below, a general one: you are adding to general use math library a fitGaus
function which in fact has nothing to do with Gaus: you are fitting the log of input data to user provided function which will be equivalent to a guassian fit provided the user supplied TLinearFitter& fitter
happens to be pol2.
What is the point of making a function with such specific requirements a general purpose function? I think it either should be defined a private method of your class, or better, implemented properly w/o user - supplied TLinearFitter: in the end, you are fitting a set of point to pol2, it takes a few lines to do this (one loop and 1 3x3 matrix inversion).
TVectorD par(3); | ||
TVectorD sigma(3); | ||
TMatrixD A(3, 3); | ||
TMatrixD b(3, 1); |
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 would not use dynamic objects where fixed size arrays would work. The matrices A, b are always filled but used only for npoints==3
for a trivial multiplication. I think these structures should be filled only if npoints==3
and if matrices to be used, it is more appropriate to use root (templated fixed size) SMatrix.
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.
Should I work on this, or should the author address the comment?
fitter.Eval(); | ||
fitter.GetParameters(par); | ||
fitter.GetCovarianceMatrix(mat); | ||
chi2 = fitter.GetChisquare() / Double_t(npoints); |
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.
why not using proper reduced chi2 definition, i.e. chi2 = fitter.GetChisquare() / (npoints - 3);
?
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.
Same as above, I am not really the author of the function.
Int_t npoints = 0; | ||
for (Int_t ibin = 0; ibin < nBins; ibin++) { | ||
Float_t entriesI = arr[ibin]; | ||
if (entriesI > 1) { |
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.
why >1
and not >0
?
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.
Same as above.
// use fitter for more than three points | ||
fitter.Eval(); | ||
fitter.GetParameters(par); | ||
fitter.GetCovarianceMatrix(mat); |
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.
note that this cov.matrix makes no sense for the final params of the fit: it is calculated for the params of pol2, which you then transform to gaussian params.
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.
And same again.
mStripOffsetFunction.append("-"); | ||
mStripOffsetFunction.append(Form("(x > %d && x < %d)", irow + 96, irow + 96 + 1)); | ||
} | ||
mStripOffsetFunction.append(Form(") ")); |
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.
out of curiosity, what does this monster function do?
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.
This function allows to fit the differences between the peaks for each channel. Using such function allows to get better results since we have 96 channels per strip to be calibrated, but we can use 144 points (all pairs between adjacent channels, adjacent in X or Z).
memset(&fracUnderPeak[0], 0, sizeof(fracUnderPeak)); | ||
memset(isChON, 0, 96); |
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.
why not defining directly fracUnderPeak[Geo::NPADS]={0} and isChON[96]={0} ?
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 want to reset it for every strip, so I need memset
, no?
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.
you could simply define them as local (in the strip loop) variable initialized by {0}, should be faster than calling memset.
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.
done, I will commit all changes in one go, for simplicity.
|
||
LOG(DEBUG) << "N real params = " << nparams << ", fitter has " << localFitter.GetNumberFreeParameters() << " free parameters, " << localFitter.GetNumberTotalParameters() << " total parameters, " << localFitter.GetNpoints() << " points"; | ||
//LOG(INFO) << "Sector = " << sector << ", strip = " << istrip << " fitted by thread = " << ithread << ": ready to fit"; | ||
printf("Sector = %d, strip = %d, fitted by thread = %d: ready to fit\n", sector, istrip, ithread); |
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.
avoid using printf, use LOG
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.
Yes, sorry. The problem was that with LOG and the thread we did not see the logs for some reason, so then we changed them to printf, but then forgot to change them again.
Do you know if it is normal that the LOG did not show?
} | ||
|
||
if (fitValues[2] < 0) { | ||
fitValues[2] = -fitValues[2]; |
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.
how this can be?
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 actually do not remember :-) @noferini , do you recall if we had seen fitValues[2] (which is the sigma) negative?
Hi @shahor02 , Before going to the specific comments:
Actually the Chiara |
The original general purpose |
Hi @shahor02 , It is for sure my ignorance, but I am not sure I understand your comment: apart from passing the matrix, which we might even be able to avoid, why is the fitGaus that we added different from the other one? We only pass the TLinearFitter, since this is probably a static object that with threads gets messed up. I would be very interested to see how to create the fitting function, if this is the way to go. Since next week we will be back to CERN, maybe we can find a slot offline to have a look together? Or if you have no time, you can point me to some documentation/examples. Thanks, Chiara |
The original version is still (in an inefficient way) fitting the logs of values to pol2 (defined in the function), which is equivalent to fitting the points to gaussian (provided the values are positive) and does not pretend to extract the errors. |
900bf5b
to
c4ff617
Compare
Hi @shahor02 . |
Hi @chiarazampolli |
Fix include of omp Remove trailing whitespaces again tabs and trailing whitespaces... ...again?... ...tabs... Whitespaces debugging fix Removing wrong call moving functions to source file to use OpenMP Does not work, but let's commit move fitter to channel offset from cosmics to TLinearFitter for omp (#39) calling FixParameter only once move to local fitter for cosmics (#40) removing obsolete code - but needs optimization fix in memory allocation TOF calib (#41) Some fixes and parallelization of the finalizeSlotWithTracks Formatting changes leftover in formatting clang-format Fixing braces
clang-format
c4ff617
to
740ca10
Compare
Hi @shahor02 , I changed the fitting as we discussed, using your new fitGaus with the medMAD to reject outliers. Thanks for this development, it is very nice! Chiara |
LOG(DEBUG) << "Strip = " << istrip << " fitted by thread = " << ithread << ", goodpoints = " << goodpoints << ", number of free parameters = " | ||
<< localFitter.GetNumberFreeParameters() << ", NDF = " << goodpoints - localFitter.GetNumberFreeParameters(); | ||
|
||
if (goodpoints <= localFitter.GetNumberFreeParameters()) { |
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.
Ciao @noferini ,
Note that here I replaced: if (goodpoints < localFitter.GetNumberFreeParameters())
with if (goodpoints <= localFitter.GetNumberFreeParameters())
(note the "<=").
Hello @TimoWilken , All tests are red, but no error is found... Any hint? Other PRs have issues, see #6772 Thanks, Chiara |
+1 |
Dear all, |
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.
forgot to merge this, sorry.
Done with @noferini .
Fix include of omp
Remove trailing whitespaces
again tabs and trailing whitespaces...
...again?...
...tabs...
Whitespaces
debugging
fix
Removing wrong call
moving functions to source file to use OpenMP
Does not work, but let's commit
move fitter to channel offset from cosmics to TLinearFitter for omp (#39)
calling FixParameter only once
move to local fitter for cosmics (#40)
removing obsolete code - but needs optimization
fix in memory allocation TOF calib (#41)
Some fixes and parallelization of the finalizeSlotWithTracks
Formatting changes
leftover in formatting
clang-format