【问题标题】:Huge memory usage in pyROOTpyROOT 中的大量内存使用
【发布时间】:2018-02-21 00:37:32
【问题描述】:

我的 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,该作业仍然只使用 python2 的 ~200 MB 内存,而 python3 使用 ~1.3 GB。

在我的谷歌搜索过程中,我遇到了其他一些关于人们在将 pyROOT 与 python3 结合使用时遇到内存泄漏的情况。从 Python 3.6.2 和 ROOT 6.08/06 开始,这似乎仍然是一个问题,目前如果你想使用 pyROOT,你必须使用 python2。

所以,目前使用 python2 似乎是我的“解决方案”,但这并不理想。如果有人有任何进一步的信息或建议,我将不胜感激!

【问题讨论】:

    标签: python memory root-framework pyroot


    【解决方案1】:

    很高兴您发现 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);
    

    这里有一个资源,您可以在其中了解 TTrees 有多棒:

    TTree ROOT documentation

    如需更多阅读,请参阅 CERN 帮助论坛上关于加快 ROOT 直方图构建的讨论:

    Memory-conservative histograms for usage in DQ monitoring

    祝您数据分析好运,编码愉快!

    【讨论】:

      猜你喜欢
      • 2014-06-28
      • 2018-04-18
      • 2017-08-08
      • 2014-04-02
      • 2014-04-06
      • 1970-01-01
      • 1970-01-01
      • 2012-01-13
      • 2023-03-24
      相关资源
      最近更新 更多