Огромное использование памяти в pyROOT
Мой код анализа pyROOT использует огромное количество памяти. Я свел проблему к примеру кода ниже:
from ROOT import TChain, TH1D
# Load file, chain
chain = TChain("someChain")
inFile = "someFile.root"
chain.Add(inFile)
nentries = chain.GetEntries()
# Declare histograms
h_nTracks = TH1D("h_nTracks", "h_nTracks", 16, -0.5, 15.5)
h_E = TH1D("h_E","h_E",100,-0.1,6.0)
h_p = TH1D("h_p", "h_p", 100, -0.1, 6.0)
h_ECLEnergy = TH1D("h_ECLEnergy","h_ECLEnergy",100,-0.1,14.0)
# Loop over entries
for jentry in range(nentries):
# Load entry
entry = chain.GetEntry(jentry)
# Define variables
cands = chain.__ncandidates__
nTracks = chain.nTracks
E = chain.useCMSFrame__boE__bc
p = chain.useCMSFrame__bop__bc
ECLEnergy = chain.useCMSFrame__boECLEnergy__bc
# Fill histos
h_nTracks.Fill(nTracks)
h_ECLEnergy.Fill(ECLEnergy)
for cand in range(cands):
h_E.Fill(E[cand])
h_p.Fill(p[cand])
где someFile.root - корневой файл с 700 000 записей и несколькими кандидатами в частицы.
Когда я запускаю этот скрипт, он использует ~600 МБ памяти. Если я уберу строку
h_p.Fill(p[cand])
он использует ~400 МБ.
Если я тоже уберу строку
h_E.Fill(E[cand])
он использует ~150 МБ.
Если я тоже уберу строки
h_nTracks.Fill(nTracks)
h_ECLEnergy.Fill(ECLEnergy)
нет дальнейшего сокращения использования памяти.
Кажется, что для каждой дополнительной гистограммы, которую я заполняю в форме
h_variable.Fill(variable[cand])
(т.е. гистограммы, которые заполняются один раз на кандидата на каждую запись, в отличие от гистограмм, которые просто заполняются один раз на каждую запись) Я использую дополнительные ~200 МБ памяти. Это становится серьезной проблемой, когда у меня есть 10 или более гистограмм, потому что я использую ГБ памяти и я превышаю пределы моей вычислительной системы. У кого-нибудь есть решение?
Обновление: я думаю, что это проблема Python3.
Если я возьму сценарий в своем исходном посте (выше) и запуском его с использованием python2, то объем используемой памяти будет ~200 МБ, по сравнению с ~600 МБ с python3. Даже если я попытаюсь воспроизвести проблему 2, используя длинные имена переменных, в задании по-прежнему используется только ~200 МБ памяти с python2, по сравнению с ~ 1,3 ГБ с python3.
Во время моего поиска в Google я столкнулся с несколькими другими учетными записями людей, которые сталкиваются с утечками памяти при использовании pyROOT с python3. Кажется, это все еще проблема с Python 3.6.2 и ROOT 6.08/06, и на данный момент вы должны использовать python2, если вы хотите использовать pyROOT.
Итак, использование python2 пока кажется моим "решением", но оно не идеально. Если у кого-либо есть какая-либо дополнительная информация или предложения, я был бы рад услышать от вас!
1 ответ
Я рад, что вы поняли, что проблема в Python3. Но если в будущем у вас (или у кого-либо еще) возникнут проблемы с использованием памяти при работе с гистограммами, вот несколько потенциальных решений, которые, я надеюсь, вы найдете полезными!
THnSparse
использование THnSparse
-THnSparse
это эффективная многомерная гистограмма, которая показывает свои сильные стороны в гистограммах, где заполнена только небольшая часть от общего числа бинов. Вы можете прочитать больше об этом здесь.
TTree
TTrees
это структуры данных в ROOT, которые являются откровенно прославленными таблицами. Тем не менее, они высоко оптимизированы. TTree
состоит из branches
а также leaves
которые содержат данные, к которым через ROOT можно быстро и эффективно получить доступ. Если вы поместите свои данные в TTree
Сначала, а затем прочитайте его в гистограмму, я гарантирую, что вы найдете меньшее использование памяти и большее время выполнения.
Вот пример TTree
код.
root_file_path = "../hadd_www.root"
muon_ps = ROOT.TFile(root_file_path)
muon_ps_tree = muon_ps.Get("WWWNtuple")
muon_ps_branches = muon_ps_tree.GetListOfBranches()
canv= ROOT.TCanvas()
num_of_events = 5000
ttvhist = ROOT.TH1F('Statistics2', 'Jet eta for ttV (aqua) vs WWW (white); Pseudorapidity',100, -3, 3)
i = 0
muon_ps_tree.GetEntry(i)
print len(muon_ps_tree.jet_eta)
#sys.exit()
while muon_ps_tree.GetEntry(i):
if i > num_of_events: break
for k in range(0,len(muon_ps_tree.jet_eta)-1):
wwwhist.Fill(float(muon_ps_tree.jet_eta[0]), 1)
i += 1
ttvhist.Write()
ttvhist.Draw("hist")
ttvhist.SetFillColor(70);
А вот ресурс, где вы можете узнать о том, как фантастически TTree
это:
Для получения дополнительной информации, вот обсуждение ускорения создания исторической диаграммы ROOT на справочном форуме CERN:
Консервативные по памяти гистограммы для использования в мониторинге DQ
Желаем удачи в анализе данных и удачного кодирования!