OrderedDict性能(与deque相比)

时间:2011-11-18 00:55:53

标签: python performance algorithm optimization

我一直在尝试使用Python来优化BFS实现,而我的原始实现是使用deque来存储节点队列以进行扩展,并使用dict来存储相同的节点,这样我就可以进行有效的查找以查看是否存在已经开放了。

我试图通过转移到OrderedDict来优化(简单性和效率)。但是,这需要更多的时间。完成400次样本搜索,使用deque / dict需要2秒,只需使用OrderedDict需要3.5秒。

我的问题是,如果OrderedDict与两个原始数据结构具有相同的功能,那么它的性能是否至少相似?或者我在这里遗漏了什么?下面的代码示例。

仅使用OrderedDict:

open_nodes = OrderedDict()
closed_nodes = {}
current = Node(start_position, None, 0)
open_nodes[current.position] = current

while open_nodes:
  current = open_nodes.popitem(False)[1]
  closed_nodes[current.position] = (current)

  if goal(current.position):
    return trace_path(current, open_nodes, closed_nodes)

  # Nodes bordering current
  for neighbor in self.environment.neighbors[current.position]:
    new_node = Node(neighbor, current, current.depth + 1)
    open_nodes[new_node.position] = new_node

同时使用双端队列和字典:

open_queue = deque()
open_nodes = {}
closed_nodes = {}
current = Node(start_position, None, 0)
open_queue.append(current)
open_nodes[current.position] = current

while open_queue:
  current = open_queue.popleft()
  del open_nodes[current.position]
  closed_nodes[current.position] = (current)

  if goal_function(current.position):
    return trace_path(current, open_nodes, closed_nodes)

  # Nodes bordering current
  for neighbor in self.environment.neighbors[current.position]:
    new_node = Node(neighbor, current, current.depth + 1)
    open_queue.append(new_node)
    open_nodes[new_node.position] = new_node

2 个答案:

答案 0 :(得分:38)

deque dict 都是用C实现的,并且运行速度比用纯Python实现的 OrderedDict 更快。

OrderedDict 的优点是它具有O(1)getitem,setitem和delitem,就像常规dicts一样。这意味着它可以很好地扩展,尽管纯python实现速度较慢。

使用deques,list或binary tree的竞争实现通常会在其中一个类别中放弃快速的大哦时间,以便在另一个类别中获得速度或空间优势。

更新:从Python 3.5开始, OrderedDict()现在有一个C实现。虽然它没有像其他一些容器那样高度优化。它应该比纯python实现更快地运行很多。然后从Python 3.6开始,已经订购了常规字典(虽然订购行为尚未得到保证)。那些应该跑得更快: - )

答案 1 :(得分:0)

就像Sven Marnach所说,OrderedDict是用Python实现的,我想补充说它是使用dictlist实现的。

python中的

dict实现为哈希表。我不确定deque是如何实现的,但文档说deque已针对快速添加或访问第一个/最后一个元素进行了优化,因此我猜deque实现为链接列表。

我认为当您在OrderedDict上执行pop时,python会执行散列表查找,与链接列表相比,后者具有指向last和first元素的直接指针。与hash-table相比,将元素添加到链表的末尾也是更快。

因此,示例中OrderDict速度较慢的主要原因是因为从链表中访问最后一个元素比使用哈希表访问任何元素更快。

我的想法基于“美丽代码”一书中的信息,它描述了dict背后的实施细节,但我不知道listdeque背后的详细信息,这个答案只是我的关于事情是如何工作的直觉,所以如果我错了,我真的应该得到投票来讨论我不确定的事情。为什么我会谈论我不确定的事情? - 因为我想测试我的直觉:)