我有多个组的 HDF5 文件,其中每个组包含一个 >= 2500 万行的数据集。在模拟的每个时间步,每个智能体输出他/她在该时间步感应到的其他智能体。场景中有大约 2000 个代理和数千个时间步长;输出的 O(n^2) 特性解释了巨大的行数。
我感兴趣的是按类别计算的独特目击次数。例如,代理属于一侧,红色、蓝色或绿色。我想制作一个二维表,其中第 i 行,第 j 列是类别j
中至少一个类别 i 中的代理感知到的类别中的代理数量。(我在此代码示例中使用 Sides,但我们也可以通过其他方式对代理进行分类,例如根据他们拥有的武器或他们携带的传感器。)
这是一个示例输出表;请注意,模拟不会输出蓝色/蓝色的感觉,因为它需要大量的空间而且我们对它们不感兴趣。绿绿相同)
blue green red
blue 0 492 186
green 1075 0 186
red 451 498 26
列是
- 滴答时间步长
- senseAgentId - 进行传感的代理的 ID
- sensedAgentId - 被感知代理的 ID
- detRange - 两个代理之间的距离(以米为单位)
- senseType - 一个枚举类型,表示进行了何种类型的传感
这是我目前用来完成此操作的代码:
def createHeatmap():
h5file = openFile("someFile.h5")
run0 = h5file.root.run0.detections
# A dictionary of dictionaries, {'blue': {'blue':0, 'red':0, ...}
classHeat = emptyDict(sides)
# Interested in Per Category Unique Detections
seenClass = {}
# Initially each side has seen no one
for theSide in sides:
seenClass[theSide] = []
# In-kernel search filtering out many rows in file; in this instance 25,789,825 rows
# are filtered to 4,409,176
classifications = run0.where('senseType == 3')
# Iterate and filter
for row in classifications:
sensedId = row['sensedAgentId']
# side is a function that returns the string representation of the side of agent
# with that id.
sensedSide = side(sensedId)
sensingSide = side(row['sensingAgentId'])
# The side has already seen this agent before; ignore it
if sensedId in seenClass[sensingSide]:
continue
else:
classHeat[sensingSide][sensedSide] += 1
seenClass[sensingSide].append(sensedId)
return classHeat
注意:我有 Java 背景,所以如果这不是 Pythonic,我深表歉意。请指出这一点并提出改进此代码的方法,我希望能更加精通 Python。
现在,这非常慢:执行此迭代和成员资格检查大约需要 50 秒,这是使用最严格的成员资格标准集(其他检测类型有更多行需要迭代)。
我的问题是,是否可以将工作从 python 移到内核搜索查询中?如果是这样,怎么做?我是否缺少一些明显的加速?我需要能够在一组运行 (~30) 和多组标准 (~5) 中为每次运行运行此功能,所以如果可以加快速度会很棒。
最后说明:我尝试使用 psyco,但这几乎没有什么不同。