Divide a process in more CPU

Hello I’ve to run a Macro and the process is very long…so I want to divide it in more CPU. I mean

1. I must open a TTree from a Root File (1e6 entries)
` TFile *fin = TFile::Open("/B1.root");`
2. I’ve to read three branches of the TTree and save the entries into arrays
``````ts->SetBranchAddress("SecondaryParticleVert.x", &xVv[0]);
``````
1. I’ve to generate 1e6 random entries and I’ve to calculate the emittance for each random entry
``````for(int jentry=0; jentry<nentries;jentry++) {
entry = gRandom->Integer(ts->GetEntries());
ts->GetEntry(entry);
x+=k*xv[0]-k*xVv[0];
x2+=(k*xv[0]-k*xVv[0])*(k*xv[0]-k*xVv[0]);
xp+=xpv[0];
xp2+=xpv[0]*xpv[0];
xxp+=(k*xv[0]-k*xVv[0])*xpv[0];
}
x*=1./nentries;
x2*=1./nentries;
xp*=1./nentries;
xp2*=1./nentries;
xxp*=1./nentries;
sigmax2=x2-x*x;
sigmaxp2=xp2-xp*xp;
sigmaxsigmaxp=xxp-x*xp;
emittance2=sigmax2*sigmaxp2-sigmaxsigmaxp;
emittance=TMath::Sqrt(emittance2);
emittance/=1000;
``````
1. I’ve to repeat the emittance calculation 100 times (i.e. I’ve to extract 100 times the 1e6 random entries)…I call the 100 times Nextractions
2. I’ve to save the results into 2 txt files
``````results << "Extraction = " << i << "\t x = " << x << "\t x2 = " << x2 << " \t xp = " << xp <<  " \t xp2= " << xp2 << " \t xxp= " <<  xxp << endl;
results << "sigmax2 = " << sigmax2 << "\t sigmaxp2 = " << sigmaxp2 << "\t sigmaxsigmaxp = " << sigmaxsigmaxp << " \t emittance = " << emittance  << endl;
resultsthf << emittance <<  endl;
``````
1. I’ve to file a TH1F
`hscoring->Fill(emittance);`
and to print it
`c0->Print("emittanceer_xxp.pdf");`

When I was using TTree having just some thousand of events I did it using one for cycle in this way:

``````int Nextraction=100;
for(i=0; i<Nextraction;i++) {
Double_t emittance=0.;
Double_t emittance2=0.;
Double_t x=0;
Double_t x2=0;
Double_t xp=0;
Double_t xp2=0;
Double_t xxp=0;
Double_t sigmax2=0;
Double_t sigmaxp2=0;
Double_t sigmaxsigmaxp=0;
int nentries = ts->GetEntries();
double xv[10];
double xVv[10];
double xpv[10];
int entry;
int k=1000000000;
for(int jentry=0; jentry<nentries;jentry++) {
entry = gRandom->Integer(ts->GetEntries());
ts->GetEntry(entry);
x+=k*xv[0]-k*xVv[0];
x2+=(k*xv[0]-k*xVv[0])*(k*xv[0]-k*xVv[0]);
xp+=xpv[0];
xp2+=xpv[0]*xpv[0];
xxp+=(k*xv[0]-k*xVv[0])*xpv[0];

}
etc.
``````

and I did it in just few time

Here the working old macro
emiter.cpp (5.4 KB)

Unfortunately, now I’ve 1e6 entries in the Root file and I need 1 day just to repeat the process 10 times (i.e. I need 10 days to repeat the process 100 times)…so I need to divide the proces in more CPU

then I was trying to divide the process on 10 CPU so that each CPU makes 10 extraction simultanley and (but I’ve to get the total results on the txt file and on the TH1F plot)

Then I was trying to write a sh shell

``````#
for i in {0..9}
do
seed=\$((\$1+i))
echo \$seed
#
nohup root -b -q '.x emiter.cpp('\$seed')'
#
done
#
``````

and I modified my macro deleting the line
` for(i=0; i<Nextraction;i++) {`

and replacing the line

``````void emiter()
{
``````

by

``````void emiter(Int_t seed=0){
TRandom *r = new TRandom();
r->SetSeed(seed);
``````

Then I uploaded my sh file and my new emiter.cpp macro on the laboratory machine and I’m trying to run the macro using the commands

``````source bootstrap_script.sh 0
source bootstrap_script.sh 10
source bootstrap_script.sh 20
...
source bootstrap_script.sh 90
``````

to get 100 simultanley extractions, but
it doesnt’ work ie. I get the error

``````Warning in <TInterpreter::ReadRootmapFile>: class  TPyArg found in libPyROOT.so  is already in libROOTTPython.so
Warning in <TInterpreter::ReadRootmapFile>: class  TPyReturn found in libPyROOT.so  is already in libROOTTPython.so
Warning in <TInterpreter::ReadRootmapFile>: class  TPython found in libPyROOT.so  is already in libROOTTPython.so
``````

Here the new macro (I don’t know if I wrote in the right place the

``````void emiter(Int_t seed=0){
TRandom *r = new TRandom();
r->SetSeed(seed);
``````

emiter.cpp (5.5 KB)

Here the shell
bootstrap_script.txt (100 Bytes)

and here the error report

nohup.txt (8.9 KB)

Does anyone know how to do what I need ?
Thank you

ROOT Version: Not Provided
Platform: Not Provided
Compiler: Not Provided

This looks like something that RDataFrame could help with. Maybe @eguiraud could give some advice once back from vacation

Hi,
if I understand correctly you are reading all data 100 times. Why don’t you instead go through the data only once, and produce 100 results for each entry you process? That should speed things up considerably.

About why the script doesn’t work, I don’t think `root -b -q '.x emiter.cpp('\$seed')'` is a valid invocation of `root`, maybe you want `root -b -q -e '.x emiter.cpp('\$seed')'` (the `-e` option can be used to tell the interpreter what to execute when it runs).

Cheers,
Enrico

Hi @eguiraud [quote=“eguiraud, post:3, topic:42840, full:true”]
Why don’t you instead go through the data only once, and produce 100 results for each entry you process? That should speed things up considerably.

[/quote]

I’m calculating the emittance of particles (muons and positrons). To do that I wrote this script:

``````	Double_t emittance=0.;
Double_t x=0;
Double_t x2=0;
Double_t xp=0;
Double_t xp2=0;
Double_t xxp=0;
Double_t sigmax2=0;
Double_t sigmaxp2=0;
Double_t sigmaxsigmaxp=0;
int jentry;
int nentries = ts->GetEntries();
double xv[10];
double xVv[10];
double xpv[10];
int k=1000000000;
for(jentry=0; jentry<nentries;jentry++) {
ts->GetEntry(jentry);
x+=k*xv[0]-k*xVv[0];
x2+=(k*xv[0]-k*xVv[0])*(k*xv[0]-k*xVv[0]);
xp+=xpv[0];
xp2+=xpv[0]*xpv[0];
xxp+=(k*xv[0]-k*xVv[0])*xpv[0];

x*=1./nentries;
x2*=1./nentries;
xp*=1./nentries;
xp2*=1./nentries;
xxp*=1./nentries;
sigmax2=x2-x*x;
sigmaxp2=xp2-xp*xp;
sigmaxsigmaxp=xxp-x*xp;
emittance=sigmax2*sigmaxp2-sigmaxsigmaxp;
emittance=TMath::Sqrt(emittance);
emittance/=1000;
``````

Now I’ve to calculate the statistical error of the emittance. To do that I use the Bootstrap method. According to this method

1. I’ve to excract N random entries; N must be equal to the total entries…ie. because I’ve 1e6 entries, I’ve to excract 1e6 random entries )
2. I’ve to extract the random entries M times (I’m starting using M=100…but maybe I need a higher M value)
3. For each extraction I’ve to calculate the emittance (i.e. If M=100, I’ve to calculate 100 times the emittance using the random values)
4. I fill a Th1f and I read the standard deviation of the th1f
5. The error to assign to the emittance is the standard deviation of the th1f…
that’s because I need to calculate emittance using random values

yes, indeed after I wrote this topic I runned the macro using

nohup root -b -q ‘emiter.cpp(’\$seed’)’

but when I run the command

bootstrap_script.sh 0

I get 10 times the same values of emittance instad of getting 10 different emittance values.
Then it looks like that it doesn’t update the seed value…do you know what is my error?

I don’t think `root -b -q '.x emiter.cpp('\$seed')'` (what you use in `bootstrap_script.sh`) is a valid invocation (you can add a printout of `seed` in the `emiter` function to check, I think you need to use `root -b -q -e '.x emiter.cpp('\$seed')'` in `boostrap_script.sh`).

Thank you @eguiraud, but as I wrote in my previous message, I runned the macro writing
nohup root -b -q ‘emiter.cpp(’\$seed’)’ (i.e. without the .x )
but I don’t get different emittance values, but I get always the same value…so I think there is an error in the macro that you can find in my first message…please, can you check the macro?

Did you check (via a simple print statement at the beginning of the macro) that the macro is run and that it get the expected value for the parameter?

Hello @pcanal
Now I wrote

``````void emiter(Int_t seed=0){
TRandom *r=new TRandom();
r->SetSeed(seed);
.
.
.
for(int jentry=0; jentry<nentries;jentry++) {
std::cout << "entry= " <<r->Integer(nentries) << std::endl;
``````

and I get the random values
but now I’ve to pass the random values to calculate the emittance ie. to do what I made by the lines

``````entry = gRandom->Integer(ts->GetEntries());
ts->GetEntry(entry);
``````

I can’t assign
`entry=*r;`
because r is a TRandom…
so what should I do to pass the values to calculate the emittance?
emiter.cpp (4.6 KB)

I am confused … Why not use

``````entry = r->Integer(nentries);
``````

?

Hi @pcanal

Before to write my previous message, I also tried

``````entry = r->Integer(nentries);
``````

But i get error because entry is an int value ansa e a TRandom…
That’s because I don’t know how to pass the values to calculate the emittance

I am fairly confused. What did you actually try and how did it fail (copy/paste of the error message).
In the last code that was uploaded replacing:

``````      std::cout << "entry= " <<r->Integer(nentries) << std::endl;
//ts->GetEntry(entry);
``````

with

``````   entry = r->Integer(nentries);
std::cout << "entry= " << entry << std::endl;
ts->GetEntry(entry);
``````

should work.

Hello @pcanal
I was sure that I wrote that code too and it didnt’work yesterday…anyway, I tried it again today
and it is working!
Thank you

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.