pyROOT中的内存使用量很大

时间:2017-09-12 13:51:35

标签: python memory root-framework 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 MB的内存。如果我删除该行

h_p.Fill(p[cand])

它使用~400 MB。

如果我也删除该行

h_E.Fill(E[cand])

它使用~150 MB。

如果我也删除了行

h_nTracks.Fill(nTracks)
h_ECLEnergy.Fill(ECLEnergy)

没有进一步减少内存使用量。

对于我填写表格

的每一个额外直方图似乎
h_variable.Fill(variable[cand])

(即每个条目每个候选填充一次的直方图,而不是每个条目只填充一次的直方图)我使用额外的~200 MB内存。当我有10个或更多直方图时,这成为一个严重的问题因为我使用的是内存GB而且我超出了我的计算系统的限制。有人有解决方案吗?

更新:我认为这是一个python3问题。

如果我在原始帖子(上面)中使用脚本并使用python2运行它,内存使用量约为200 MB,而使用python3则为~600 MB。即使我尝试使用长变量名复制问题2,作业仍然只使用~200 MB内存和python2,而使用python3约为1.3 GB。

在谷歌搜索期间,我遇到了一些其他人在使用python与python3时遇到内存泄漏的问题。从Python 3.6.2和ROOT 6.08 / 06开始,这似乎仍然是一个问题,如果你想使用pyROOT,你现在必须使用python2。

所以,使用python2似乎是我的解决方案"现在,但它并不理想。如果有人有任何进一步的信息或建议,我将非常感谢您的来信!

1 个答案:

答案 0 :(得分:0)

我很高兴你发现Python3是个问题。但是,如果您(或任何人)在将来使用直方图时仍然存在内存使用问题,我希望您能找到一些有用的解决方案!

THnSparse

使用THnSparse - THnSparse是一个有效的多维直方图,显示其在直方图中的优势,其中只有一小部分总分数被填充。 You can read more about it here.

TTree

TTrees是ROOT中的数据结构,是非常坦诚的表格。但是,它们高度优化TTreebranchesleaves组成,其中包含通过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的精彩程度:

TTree ROOT documentation

有关更多阅读,以下是关于在CERN帮助论坛上加快ROOT历史记录的讨论:

Memory-conservative histograms for usage in DQ monitoring

祝您的数据分析和编码愉快!