【问题标题】:Python, PyTables - taking advantage of in-kernel searchingPython、PyTables - 利用内核搜索
【发布时间】:2010-12-30 14:55:45
【问题描述】:

我有多个组的 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

列是

  1. tick - 时间步长
  2. sensingAgentId - 进行传感的代理的 ID
  3. sensedAgentId - 被感知代理的 ID
  4. detRange - 两个代理之间的距离(以米为单位)
  5. 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,但几乎没有什么不同。

【问题讨论】:

  • 你能发布一个精简的测试 .h5 文件进行测试吗?我有一些想法,但是用一些半真实的数据来验证它们会更容易。

标签: python optimization query-optimization pytables


【解决方案1】:

如果您有 N=~2k 代理,我建议将所有目击记录放入一个大小为 NxN 的 numpy 数组中。这很容易放入内存中(整数约为 16 兆)。只要在发生目击事件的地方存储一个 1。

假设您有一个数组sightings。第一个坐标是 Sensing,第二个是 Sensed。假设您还有一维索引数组,列出了哪些代理在哪一侧。您可以通过这种方式获得 A 面的 B 面目击次数:

sideAseesB = sightings[sideAindices, sideBindices]
sideAseesBcount = numpy.logical_or.reduce(sideAseesB, axis=0).sum()

您可能需要在第一步中使用sightings.take(sideAindices, axis=0).take(sideBindices, axis=1),但我对此表示怀疑。

【讨论】:

  • 我错了,您确实需要Sightings.take(...).take(...) 位。 (我更新了 pastebin)
猜你喜欢
  • 2013-02-03
  • 2019-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-28
相关资源
最近更新 更多