This repository has been archived by the owner on Jan 7, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #264 from ndawe/master
Docs: include benchmark plot for tree2array
- Loading branch information
Showing
8 changed files
with
223 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*.pkl |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from rootpy.io import TemporaryFile | ||
import rootpy | ||
from root_numpy import array2tree | ||
import numpy as np | ||
import uuid | ||
import random | ||
import string | ||
import timeit | ||
import pickle | ||
import platform | ||
import matplotlib.pyplot as plt | ||
|
||
with open('hardware.pkl', 'r') as pkl: | ||
info = pickle.load(pkl) | ||
|
||
# construct system hardware information string | ||
hardware = '{cpu}\nStorage: {hdd}\nROOT-{root} Python-{python} NumPy-{numpy}'.format( | ||
cpu=info['CPU'], hdd=info['HDD'], | ||
root=rootpy.ROOT_VERSION, python=platform.python_version(), | ||
numpy=np.__version__) | ||
|
||
rfile = TemporaryFile() | ||
|
||
def randomword(length): | ||
return ''.join(random.choice(string.lowercase) for i in range(length)) | ||
|
||
def make_tree(entries, branches=10, dtype=np.double): | ||
dtype = np.dtype([(randomword(20), dtype) for idx in range(branches)]) | ||
array = np.zeros(entries, dtype=dtype) | ||
return array2tree(array, name=uuid.uuid4().hex) | ||
|
||
# time vs entries | ||
num_entries = np.logspace(1, 7, 20, dtype=np.int) | ||
root_numpy_times = [] | ||
root_times = [] | ||
for entries in num_entries: | ||
print(entries) | ||
iterations = 20 if entries < 1e5 else 4 | ||
tree = make_tree(entries, branches=1) | ||
branchname = tree.GetListOfBranches()[0].GetName() | ||
root_numpy_times.append( | ||
min(timeit.Timer('tree2array(tree)', | ||
setup='from root_numpy import tree2array; from __main__ import tree').repeat(3, iterations)) / iterations) | ||
root_times.append( | ||
min(timeit.Timer('draw("{0}", "", "goff")'.format(branchname), | ||
setup='from __main__ import tree; draw = tree.Draw').repeat(3, iterations)) / iterations) | ||
|
||
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5)) | ||
|
||
ax1.plot(num_entries, root_numpy_times, '-o', label='root_numpy.tree2array()', linewidth=1.5) | ||
ax1.plot(num_entries, root_times, '--o', label='ROOT.TTree.Draw()', linewidth=1.5) | ||
ax1.set_xscale("log", nonposx='clip') | ||
ax1.set_yscale("log", nonposx='clip') | ||
ax1.legend(loc='lower right', frameon=False, fontsize=12) | ||
ax1.set_ylabel('time [s]') | ||
ax1.set_xlabel('number of entries') | ||
ax1.text(0.05, 0.95, 'tree contains a single branch', | ||
verticalalignment='top', horizontalalignment='left', | ||
transform=ax1.transAxes, fontsize=12) | ||
ax1.text(0.05, 0.85, hardware, | ||
verticalalignment='top', horizontalalignment='left', | ||
transform=ax1.transAxes, fontsize=10) | ||
|
||
# time vs branches | ||
num_branches = np.linspace(1, 10, 10, dtype=np.int) | ||
root_numpy_times = [] | ||
root_times = [] | ||
for branches in num_branches: | ||
print(branches) | ||
tree = make_tree(1000000, branches=branches) | ||
branchnames = [branch.GetName() for branch in tree.GetListOfBranches()] | ||
branchname = ':'.join(branchnames) | ||
root_numpy_times.append( | ||
min(timeit.Timer('tree2array(tree)', | ||
setup='from root_numpy import tree2array; from __main__ import tree').repeat(3, 3)) / 3) | ||
root_times.append( | ||
min(timeit.Timer('draw("{0}", "", "goff candle")'.format(branchname), | ||
setup='from __main__ import tree; draw = tree.Draw').repeat(3, 3)) / 3) | ||
|
||
ax2.plot(num_branches, root_numpy_times, '-o', label='root_numpy.tree2array()', linewidth=1.5) | ||
ax2.plot(num_branches, root_times, '--o', label='ROOT.TTree.Draw()', linewidth=1.5) | ||
ax2.legend(loc='lower right', frameon=False, fontsize=12) | ||
ax2.set_ylabel('time [s]') | ||
ax2.set_xlabel('number of branches') | ||
ax2.text(0.05, 0.95, 'tree contains 1M entries per branch', | ||
verticalalignment='top', horizontalalignment='left', | ||
transform=ax2.transAxes, fontsize=12) | ||
|
||
fig.tight_layout() | ||
fig.savefig('bench_tree2array.png', transparent=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
""" | ||
Get system hardware information | ||
http://stackoverflow.com/a/4194146/1002176 | ||
""" | ||
import cpuinfo | ||
import sys, os, fcntl, struct | ||
import pickle | ||
|
||
if os.geteuid() > 0: | ||
print("ERROR: Must be root to use") | ||
sys.exit(1) | ||
|
||
with open(sys.argv[1], "rb") as fd: | ||
# tediously derived from the monster struct defined in <hdreg.h> | ||
# see comment at end of file to verify | ||
hd_driveid_format_str = "@ 10H 20s 3H 8s 40s 2B H 2B H 4B 6H 2B I 36H I Q 152H" | ||
# Also from <hdreg.h> | ||
HDIO_GET_IDENTITY = 0x030d | ||
# How big a buffer do we need? | ||
sizeof_hd_driveid = struct.calcsize(hd_driveid_format_str) | ||
|
||
# ensure our format string is the correct size | ||
# 512 is extracted using sizeof(struct hd_id) in the c code | ||
assert sizeof_hd_driveid == 512 | ||
|
||
# Call native function | ||
buf = fcntl.ioctl(fd, HDIO_GET_IDENTITY, " " * sizeof_hd_driveid) | ||
fields = struct.unpack(hd_driveid_format_str, buf) | ||
hdd = fields[15].strip() | ||
|
||
cpu = cpuinfo.get_cpu_info()['brand'] | ||
|
||
print(cpu) | ||
print("Hard Drive Model: {0}".format(hdd)) | ||
|
||
info = { | ||
'CPU': cpu, | ||
'HDD': hdd, | ||
} | ||
|
||
with open('hardware.pkl', 'w') as pkl: | ||
pickle.dump(info, pkl) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../benchmarks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters