2017-09-12 63 views
1

我的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是與700000個條目和每個條目的多個粒子的候選人的根文件。

當我運行這個腳本時,它使用〜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。

在我的谷歌搜索過程中,我遇到了python3使用pyROOT時遇到內存泄漏的人的一些其他帳戶。看來這仍然是Python 3.6.2和ROOT 6.08/06的一個問題,如果你想使用pyROOT,那麼你現在必須使用python2。

所以,現在使用python2似乎是我的「解決方案」,但它並不理想。如果有人有任何進一步的信息或建議,我會很高興聽到你的消息!

回答

0

我很高興你想出了Python3是個問題。但是如果你(或者任何人)在將來使用直方圖時仍然會遇到內存使用問題,我希望你能找到一些有用的解決方案。

THnSparse

使用THnSparse - THnSparse是一種高效的多維直方圖顯示其直方圖中只有總倉的一小部分都充滿力量。You can read more about it here.

TTree

TTrees在ROOT數據結構是很坦率地說相映生輝表。但是,他們高度優化。 A 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 S如何奇妙的是:

TTree ROOT documentation

更多的閱讀,這裏是在CERN的幫助論壇加快ROOT historgram建設的討論:

Memory-conservative histograms for usage in DQ monitoring

祝您好運與您的數據分析,和快樂的編碼!