首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >改进一个分支的Uproot4根树文件输入反序列化

改进一个分支的Uproot4根树文件输入反序列化
EN

Stack Overflow用户
提问于 2022-04-20 23:17:10
回答 1查看 134关注 0票数 1

我使用链接来访问Python中的根树,并且当我尝试访问一个特定的分支: wf,它包含一个锯齿状数组时,我注意到了一个显著的放缓。

根枝

我使用延迟/尴尬的方法访问分支,并使用step_size选项。

代码语言:javascript
复制
LazyFileWF = uproot.lazy('../Layers9_Xe_Phantom102_run1.root:dstree;111', filter_name= "wf",step_size=100)

当我想要访问"LazyFileWF“中的条目时,我经历了6到10秒的慢下来,但是如果我继续到下一个连续的条目,它只需要14 ms直到step_size的结束。但是,我的脚本需要随机选择条目,而不是顺序选择,这意味着每个条目将花费我大约8秒的时间访问。我能够相当快地从其他分支访问数据,除了这个分支,我想知道原因。

通过使用uproot.open().show(),我注意到对分支的解释被标记为AsObjects(AsObjects(AsVector(True, AsVector(False, dtype('>f4'))))

我在文档中做了一些调查,发现如下:

根除AsObjects医生

它提到我可以使用simplify来改进缓慢的反序列化。

因此,我想知道的是,基于我的根树,我可以使用simplify来减少8秒的减速来访问我的分支吗?如果是这样的话,如何实现呢?有更好的方法来阅读这个分支吗?

我试过:

代码语言:javascript
复制
a = uproot.AsObjects.simplify(LazyFileWF.wf)
a

但我跟我说错了

代码语言:javascript
复制
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/tmp/ipykernel_147439/260639244.py in <module>
      5 LazyFileWF = uproot.lazy('../Layers9_Xe_Phantom102_run1.root:dstree;111', filter_name= "wf",step_size=100)
      6 events.show(typename_width=35, interpretation_width= 60)
----> 7 a = uproot.AsObjects.simplify(LazyFileWF.wf)
      8 a

~/anaconda3/envs/rapids-21.10/lib/python3.7/site-packages/uproot/interpretation/objects.py in simplify(self)
    245         ``self``.
    246         """
--> 247         if self._branch is not None:
    248             try:
    249                 return self._model.strided_interpretation(

~/anaconda3/envs/rapids-21.10/lib/python3.7/site-packages/awkward/highlevel.py in __getattr__(self, where)
   1129                 raise AttributeError(
   1130                     "no field named {0}".format(repr(where))
-> 1131                     + ak._util.exception_suffix(__file__)
   1132                 )
   1133 

AttributeError: no field named '_branch'

(https://github.com/scikit-hep/awkward-1.0/blob/1.7.0/src/awkward/highlevel.py#L1131)
EN

回答 1

Stack Overflow用户

发布于 2022-04-21 16:02:57

AsObjects.simplify函数在内部应用以生成默认的TBranch.interpretation,如果在将TBranch作为数组加载时不覆盖TBranch,则使用该函数。您传递自定义interpretation的唯一原因是,如果默认设置错误--这是修复错误自动检测interpretation的案例的后门。

如果默认的TBranch.interpreation

代码语言:javascript
复制
AsObjects(AsVector(True, AsVector(False, dtype('>f4')))

然后,它确实尝试了简化--即用AsObjects替换为AsStridedObjectsAsJagged-but不能。这一定是一个C++ std::vector<std::vector<float>>,每个对象的字节数是可变的,因此没有任何简化的解释能够工作。AsStridedObjectsAsJagged的“简化”之处在于,它们每个对象都有固定数量的字节,因此可以批量解释,而无需对TBasket中的所有项执行Python循环。

顺便说一句,我们在https://arxiv.org/abs/2102.13516中研究了这个精确的情况,本文中描述的AwkwardForth解决方案将在今年夏天被改编成连根拔起。不幸的是,这对你现在没有帮助。

您所看到的慢-快速模式是因为每次您从不同的TBasket请求一个条目时,链接都会解释整个TBasket。如果您是按顺序运行的,您将在每个TBasket的开头看到一个暂停。惰性数组缓存解释过的数据,所以当随机访问返回到先前读取的TBasket时,它应该再次快速:只看前几个请求,您就会感觉每个请求都会很慢,但这只是因为早期请求更有可能击中未读的TBaskets而不是延迟的请求。

如果您只是因为整个进程太慢(即只让它运行并填充它的缓存不够好),那么考虑将整个TBranch读入一个数组并随机访问该数组。如果您的随机访问是在Python循环中(而不是Numba),那么在尴尬的数组上调用__getitem__ (而不是NumPy数组)也没有什么可获得的,也没有一些性能损失,所以请传递library="np"

如果您没有足够的内存将整个TBranch加载到一个数组中--这可以解释为什么要使用惰性数组--那么您就处于一个困难的位置,因为惰性数组的缓存会对您不利:它将从缓存中排除已经有一段时间没有命中的TBaskets,因此即使是长时间运行的进程也会重复读取/解释。这是内存太大的数据随机访问问题的一个根本问题:没有一种很好的方法来缓存它,因为新的请求不断地将旧的结果从缓存中推出来。(同样的问题也适用于磁盘访问、web缓存的数据、数据库等)

希望这个数组适合内存,您可以在内存中随机访问它。尴尬的数组的__getitem__比NumPy慢,但是它们在内存中更紧凑,所以哪一个最适合您,这取决于细节。

希望这些指点能帮上忙!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71947132

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档