(Re)load function used in fitting

Hi,

I’ve got a quite technical question. I’m fitting some data using TMinuit, and
the setup procedure takes quite some time and I’m still debugging my
fit function so I spend quite some time waiting for the setup to finish
in order to test the function itself. Now, in one source file I got something
like

void GetSquareSum(); //Only declared here

void Chi2(Int_t &npar, Double_t* grad, Double_t& fval, Double_t* par,
Int_t flag) {

.
.
.
GetSquareSum(…);
.
.
.

}

TMinuit *fMyFitter = new TMinuit(95);
fMyFitter->SetFCN(Chi2);

while GetSquareSum(…) is implemented in another file. Is there a
way I can “relink” the loaded libraries and just change GetSquareSum()
without having to reload everything? Had I been working outside of ROOT
I would have used dlopen and a function pointer. Should I do this here
as well?

kind regards

Joa Ljungvall

Hello,

I am not sure I have understood your problem. If you are working from the ROOT prompt, running the application interactively or using ACLIC you can load the file (or library) implementing the minimization function by doing root>.L GetSquareSum.C+

GetSquareSum.C is the file implementing your function and the “+” is need if you want the code compiled. If you are not runnining from the ROOT prompt you can then use gROOT->ProcessLine

Best Regards

Lorenzo

Hi,

I’m probably not so clear then :wink: Seems to be a problem of mine on this
page…

I want to change how I calculate the square sum, i.e. GetSquareSum(), without having to reload the chi2 function I use for the the TMinuit fitter
object. I tried naively to reload the GetSquareSum function using

root> .L GetSquareSum.cxx+

but my Chi2 function still uses the old GetSquareSum when I do the fit.
This is what I would like to change without having to recompile the chi2 function, which would remove some variables I want to keep. I could possible rewrite the code so I use TMinuit::SetFCN instead, but I prefer
not to do it that way.

cheers

Joa

The reloading should work. You should post a simplified running example reproducing your problem, so we can understand why is not working for you

Best Regards

Lorenzo

Hi,

first

root-config --version --arch ->
5.27/01 macosx64

So, with my included test case (simple at least) I would like to get

root [0] .L sqsum.cxx+
root [1] .L fit.cxx+
root [2] fit()
(double)1.00000000000000000e+00
root [3] .L sqsum2.cxx+
Info in TUnixSystem::ACLiC: creating shared library /users/joa/test/root/./sqsum2_cxx.so
root [4] fit()
(double)2.00000000000000000e+00 !!!

but I get

root [0] .L sqsum.cxx+
root [1] .L fit.cxx+
root [2] fit()
(double)1.00000000000000000e+00
root [3] .L sqsum2.cxx+
Info in TUnixSystem::ACLiC: creating shared library /users/joa/test/root/./sqsum2_cxx.so
root [4] fit()
(double)1.00000000000000000e+00 !!!

It is clear why, in fit_cxx.so the double squaresum() from sqsum.cxx is
still used. Doing

root [1] .L sqsum2.cxx++
Info in : unmodified script has already been compiled and loaded
Info in : it will be regenerated and reloaded!
Info in TUnixSystem::ACLiC: creating shared library /users/joa/test/root/./sqsum2_cxx.so
root [2] .L fit.cxx+
root [3] fit()
(double)2.00000000000000000e+00
root [4] .q
A-MacBook-Pro:root joa$ root -l
root [0] .L sqsum.cxx+
Info in TUnixSystem::ACLiC: creating shared library /users/joa/test/root/./sqsum_cxx.so
root [1] .L fit.cxx+
root [2] fit()
(double)1.00000000000000000e+00 !!!
root [3]

it is also clear that root is doing the “right” thing when linking. My question
was how can I replace the squaresum() in sqsum.cxx with the one in
sqsum2.cxx without loosing any other variables etc? If the answer is too use dlopen etc I know how to do it, but I hoped there was a simple solution
I missed using the “.L” of root

cheers

Joa
test.tar.gz (234 Bytes)

Hi again,

just to be complete, here is what I came up with…

cheers

Joa
test.tar.gz (488 Bytes)

Hi,

your script does not work because you cannot have two implementations of the same symbols in two libraries.
You should use two function names, since you are using a function pointer you can set easily to one of the name as you wish.
Or, if you are using Minuit, via the new Minimizer interface you can have two different objects implementing the function via the same interface.
This is much simpler and it will solve your use case

Best Regards

Lorenzo

Hi Joa,

To insure that in the general case library loading and unloading works, the .L library loading function is keeping track of dependencies between libraries. At the moment this dependency tracking is very simply based on the order of loading; i.e. .L assumes that if you loaded library B after library A, it might use any symbols coming from library A. In particular some of this symbols might be a class definition, in particular a class size (for example you might have ‘class A { … };’ and ‘class B { … A fObject; }’. So this means that if A is unloaded and reloaded, the definition and size of A might have changed, if this happens, the B class definition and the B object we may have allocated are now invalidated (i.e. using the old object or the old class B definition will lead to certain data corruption and/or crashes).

So as you found out, you would need to either load the library containing the actual function definition as the last library via .L or, as you did, take that library loading out of band from the .L. In addition to the dlopen you have in SetSuareum you probably should unload (dlclose) the previous one to avoid confusing the linker ; also to avoid potential confusion, as Lorenzo pointed out, you ought to use a different name for the pointer to function and the functions themselves.

More over, as Lorenzo pointed out, it might be simplier (and more C++ ‘like’ :slight_smile:) to use a series of concrete implementation of a base/interface class instead.

Cheers,
Philippe.

Yes, the slightly simpler

.L Squaresum1.cxx (double Squaresum1()…)
squaresum = &Squaresum1;
.L Squaresum2.cxx (double Squaresum2()…)
squaresum = &Squaresum2;

would of course also do…

Thanks for the help

cheers

Joa