Parallelization inside a ROOT macro


Please read tips for efficient and successful posting and posting code

_ROOT Version:6.22/08
_Platform: linuxx8664gcc
Compiler: Not Provided


Dear colleagues,

I have found some answers about parallelization on other forum pages, but I still do not find the one I am looking for.
How, if possible, to parallelize a function within a ROOT macro?
To give some context, I give you an example pretty close to what I am doing:

void func_parallel();

void my_macro(){
 /// some code
}

void func_parallel(){
    // Section I want to parallelize
    for (){
        // heavy code
    }
}

This func_parallel() does not handle the same ROOT object simultaneously, so there should be no thread write/read conflict.

In compile code, I usually would use “omp” library:

#pragma omp parallel for

But I do not know how to proceed with macros.

Thanks in advance for the help.

Dario

I suppose you already searched the forum, right? And if RDataFrame doesn’t help, then I think you’ll have to use std::thread. You can take a look at the examples in tutorials\multicore

Hi, I find the solution in the tutorials partially.

void my_parallel_func();
void save_objs();

void my_macro(){
    my_parallel_func();
    save_objs();
}

void my_parallel_func(){
    gROOT->SetBatch();

    const UInt_t n_thread = 16;

    // This function contains what was before inside the for loop
    auto work_item = [](size_t thread_id) {
         /// heavy code
        // Creating TObjects and save them to some containers
        return 0;
    };

    // Create the pool of workers
   ROOT::TProcessExecutor workers(n_thread );

   // Fill the pool with work
   workers.Map(work_item , ROOT::TSeqI(n_thread ));
   // This replaces the for loop and parallelized
}

After my_parallel_func is called, a different function is called to save all objects stored in some containers: objects created for individual pool tasks. But seems that function is called even before the works in the pools have finished cause those objects created are never saved.

Is there a way to check whether an individual task or the entire pool is finished??

I don’t know. We need a specialist here. Maybe @eguiraud can give some hints?

Hi @Dario_Ramirez ,

the behavior you see is unexpected and I cannot reproduce it. Map should only return when all tasks are done.

Indeed that’s what happens when I run this version of your example where I added a couple of printouts to check the order of operations:

// my_macro.C
void save_objs() { std::cerr << "saving objs\n"; }

void my_parallel_func() {
  gROOT->SetBatch();

  const UInt_t n_thread = 16;

  // This function contains what was before inside the for loop
  auto work_item = [](size_t thread_id) {
    /// heavy code
    // Creating TObjects and save them to some containers
    std::cerr << "task for " << thread_id << " done.\n";
    return 0;
  };

  // Create the pool of workers
  ROOT::TProcessExecutor workers(n_thread);

  // Fill the pool with work
  workers.Map(work_item, ROOT::TSeqI(n_thread));
  // This replaces the for loop and parallelized
}

void my_macro() {
  my_parallel_func();
  save_objs();
}

Here is the output of 3 example executions, you can see saving objs is always printed after the tasks are done (while the tasks running concurrently sometimes messes up their printouts):

/tmp root -l -b -q my_macro.C

Processing my_macro.C...
task for 0task for  done.
2 done.
task for 1 done.
task for 3 done.
task for task for 5 done.
task for 6 done.
4 done.
task for 13 done.
task for 8 done.
task for 9 done.
task for 11 done.
task for 10 done.
task for 7 done.
task for 12 done.
task for 14 done.
task for 15 done.
saving objs
/tmp root -l -b -q my_macro.C

Processing my_macro.C...
task for 0 done.
task for 2 done.
task for 1 done.
task for 5 done.
task for 3 done.
task for 4 done.
task for 6 done.
task for 8 done.
task for 7 done.
task for 9 done.
task for 13 done.
task for 12 done.
task for 10 done.
task for 11 done.
task for 14 done.
task for 15 done.
saving objs
/tmp root -l -b -q my_macro.C

Processing my_macro.C...
task for 0 done.
task for 3 done.
task for 1task for  done.
2 done.
task for 4 done.
task for 5 done.
task for task for task for task for 13task for 6task for  done.
109 done.
 done.
11 done.
task for 8 done.
7 done.
 done.
task for 12 done.
task for 14 done.
task for 15 done.
saving objs

Feel free to provide a self-contained reproducer for your issue that we can use to debug what is happening.

Cheers,
Enrico

Thanks a lot. This clarifies my initial questions. As the problem I have now is a different topic, I will close this one and thank you again for the help!!!

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