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]);
			ts->SetBranchAddress("PositionDirection.x", &xv[0]);
			ts->SetBranchAddress("SecondaryParticleAng.x", &xpv[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;
			ts->SetBranchAddress("SecondaryParticleVert.x", &xVv[0]);
			ts->SetBranchAddress("PositionDirection.x", &xv[0]);
			ts->SetBranchAddress("SecondaryParticleAng.x", &xpv[0]);
		   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 
Warning in <TApplication::GetOptions>: macro .x emiter.cpp not found

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


Please read tips for efficient and successful posting and posting code

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;
			ts->SetBranchAddress("SecondaryParticleVert.x", &xVv[0]);
			ts->SetBranchAddress("PositionDirection.x", &xv[0]);
			ts->SetBranchAddress("SecondaryParticleAng.x", &xpv[0]);
		    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.