<p>请注意,对<code>uproot.open(...)</code>和<code>file [key]</code>的每次调用都使用纯Python加载TFile和TTree元数据,这是outlot中最慢的部分。如果您多次调用它,请尝试保留TFile和/或TTree对象并重新使用它们。你知道吗</p>
<p>另外,看起来你的<code>dropAndKeep</code>函数只是在删除行(事件),但是如果我读错了,它在做列(分支),那么就使用rubot的数组读取函数的<code>branches</code>参数来只发送你想要的分支。由于根文件中的数据是按列排列的,因此无法避免读取不需要的事件(在任何框架中)必须在事后剪切它们。你知道吗</p>
<p>接下来,请注意,对于过滤事件之类的简单操作,Pandas要比NumPy慢得多。如果你想加快速度,用<code>TTree.arrays</code>而不是<code>TTree.pandas.df</code>得到数组,为你的选择构造一个布尔数的NumPy数组,并将它应用到<code>TTree.arrays</code>返回的dict中的每个数组。然后您可以使用Pandas的DataFrame构造器将所有这些内容放入一个DataFrame中(如果您真的需要Pandas的话)。你知道吗</p>
<p>的确,你不需要通过HDF5,也不需要通过Pandas。你的机器学习框架(TensorFlow?手电筒?)几乎可以肯定的是,它有一个接口可以接受零拷贝的NumPy数组(或者一个拷贝到GPU)。强调HDF5或Pandas的教程之所以这样做,是因为对于大多数用户(非HEP)来说,它们是最方便的接口。他们的数据可能已经在HDF5或Pandas中;我们的数据可能在ROOT中。你知道吗</p>
<p>如果您的机器学习将在GPU上,也许您也希望在GPU上进行事件选择。<a href="https://cupy.chainer.org/" rel="nofollow noreferrer">CuPy</a>是完全在GPU上分配和操作的NumPy克隆,您的TensorFlow/Torch张量可能有一个到CuPy数组的零拷贝接口。原则上,如果将CuPy数组用作<a href="https://uproot.readthedocs.io/en/latest/interpretation.html#uproot-interp-numerical-asarray" rel="nofollow noreferrer">asarray interpretation</a>的目标,则outlot应该能够直接从根文件写入CuPy数组。不过,我还没试过。你知道吗</p>
<p>如果您对要处理的根文件有控制权,请尝试使它们的篮子变大(增加刷新大小)并且使它们的数据结构简单(例如纯数字或数字的数组/向量,不要更深)。也许最重要的是,使用像lz4这样的轻量级压缩,而不是重量级的lukelzma。你知道吗</p>
<p>rubot可以并行读取篮子,但是只有当它有很多非Python计算要做时,比如解压缩lzma时,它才被证明是有用的。你知道吗</p>
<p>如果要反复读取这些数组,可能需要使用<a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.save.html" rel="nofollow noreferrer">numpy.save</a>来编写中间文件,这实际上只是磁盘上的原始字节。这意味着在读回时没有反序列化,而不是解码根文件或HDF5文件所需的工作。因为它是如此简单的格式,你甚至可以用<a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html" rel="nofollow noreferrer">numpy.memmap</a>读回它,当它从磁盘懒洋洋地加载数据,甚至删除字节的显式副本时,它会窥视操作系统的页面缓存。你知道吗</p>
<p>并非所有这些技巧都同样有用。我试着把最重要的放在第一位,但在进行一个可能不会有太大影响的大型代码重写之前先做实验。有些技巧不能与其他技巧结合使用,例如CuPy和memmap(memmap总是懒洋洋地加载到主内存,而不是GPU内存)。但有些组合可能是有成效的。你知道吗</p>
<p>祝你好运!你知道吗</p>