ROOT и OpenMp
Распараллеливание анализа данных в среде ROOT можно производить с использованием технологии OpenMP. В частности, с использованием openMP написана библиотека Minuit2. При работе с этой библиотекой необходимо установить переменные среды USE_PARALLEL_MINUIT2 и USE_OPENMP.
Также технология OpenMP применяется в пакете TMVA - комплексном инструментарии для многомерного анализа данных в ROOT. В классах, реализующих генетический алгоритм: GeneticAlgorithm, GeneticPopulation - с помощью OpenMP распараллелены большие циклы. В классе FitUtil математической библиотеки реализован метод FitUtilParallel().
И наконец, ROOT разрешает выполнение макросов пользователей, написанных с использованием процедур библиотеки OpenMP, но на данный момент только в batch-режиме.
Рассмотрим пример, как запустить заполнение гистограмм с использованием OpenMP.
Первый шаг - редактирование файла .bashrc. В этот файл необходимо добавить адрес, по которому расположен ROOT на Вашей машине. Например, для кластера hybrilit:
# .bashrc .................... .................... .................... # User specific aliases and functions export ROOTSYS=/cvmfs/hybrilit.jinr.ru/sw/root export PATH=$PATH:$ROOTSYS/bin export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOTSYS/lib
Далее, чтобы получить доступ к OpenMP в макрос пользователя необходимо добавить
#include <omp.h>
Ниже приведен код макроса, в котором происходит розыгрыш случайного числа, вычисления с этим числом и заполнение гистограмм
#include "TROOT.h" #include "TH1F.h" #include "TRandom.h" #include "TCanvas.h" #include "TFrame.h" #include "TDatime.h" #include "TF1.h" #include "TFile.h" #include "TStopwatch.h" #include <iostream> #include <omp.h> using namespace std; int main(){ gROOT->Time(); TStopwatch timer; Int_t nHist=48; Long64_t n=10000000; TH1F *fH1F[48]; Int_t i,j; Double_t y; TRandom *fRandom=new TRandom(); TFile *f=new TFile("ompYes.root","recreate"); cout<<"max threads="<<omp_get_max_threads()<<endl; timer.Start(); for(i=0;i<nHist;i++){ fH1F[i] = new TH1F(Form("hpx%d",i),"The px distribution",200,0,200); } #pragma omp parallel for shared(fH1F) private(j,i) for(i=0;i<nHist;i++){ for(j=0;j<n;j++){ Double_t x=fRandom->Gaus(0.,i+1.); y=sqrt(x*x*x*x+x*x+1)-cos(x+5)*sin(x-5); fH1F[i]->Fill(y); } } f->Write(); timer.Stop(); cout<<"time: "; timer.Print("m"); f->Close(); return 0; }
Для компиляции макроса необходимо выполнить команду
g++ -fopenmp NameMacros.C `root-config --cflags --libs`
При успешной компиляции образуется исполняемый бинарный файл. По умолчанию имя бинарного файла - a.out . Подробно о том, как запускать OpenMP-приложения на кластере hybrilit можно посмотреть здесь. Здесь приведем рекомендуемый вид script-файла, например, с 12-ю потоками:
#!/bin/sh #SBATCH -p cpu #SBATCH -c 12 #SBATCH t 60 export OMP_NUM_THREADS=12 export OMP_PLACES=cores ./a.out
Для запуска приложения используется следующая команда:
$ sbatch omp_script
Следует отметить, что используя OpenMP можно легко распараллелить арифметические операции, встречающиеся в макросах. Специфические же методы пакета ROOT часто не допускают распараллеливания с помощью этой технологии. Например, классы TTree и TFile не являются потокобезопасными, поскольку манипулируют глобальными данными, и не все эти данные полностью защищены для обеспечения безопасности потоков.Поэтому объекты этих классов не должны использоваться совместно (без блокировки) между потоками. Однако можно создать несколько объектов TFile (и, следовательно, объектов TTree), считывая один и тот же физический файл.
Следует учитывать тот факт, что на образование потоков тоже расходуется время. Может случиться так, что выйгрыш во времени от работы программы на нескольких потоках будет меньше, чем время, потраченное на образование потоков. Использование OpenMP оправдано только лишь в том случае, если в каждом потоке выполняется значительное количество арифметических операций. В ином случае для распараллеливания программы предпочтительнее использовать PROOF. По этой ссылке можно найти пример (скачать файл), в котором сравнивается эффективность распараллеливания программ с помощью OpenMP и PROOF.