Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 设置与冻结设置性能_Python_Performance_Set_Frozenset - Fatal编程技术网

Python 设置与冻结设置性能

Python 设置与冻结设置性能,python,performance,set,frozenset,Python,Performance,Set,Frozenset,我正在修补Python的set和frozenset集合类型 最初,我假设frozenset将提供比set更好的查找性能,因为它是不可变的,因此可以利用存储项的结构 然而,关于以下实验,情况似乎并非如此: import random import time import sys def main(n): numbers = [] for _ in xrange(n): numbers.append(random.randint(0, sys.maxint))

我正在修补Python的
set
frozenset
集合类型


最初,我假设
frozenset
将提供比
set
更好的查找性能,因为它是不可变的,因此可以利用存储项的结构

然而,关于以下实验,情况似乎并非如此:

import random
import time
import sys

def main(n):
    numbers = []
    for _ in xrange(n):
        numbers.append(random.randint(0, sys.maxint))
    set_ = set(numbers)
    frozenset_ = frozenset(set_)

    start = time.time()
    for number in numbers:
        number in set_
    set_duration = time.time() - start

    start = time.time()
    for number in numbers:
        number in frozenset_
    frozenset_duration = time.time() - start

    print "set      : %.3f" % set_duration
    print "frozenset: %.3f" % frozenset_duration


if __name__ == "__main__":
    n = int(sys.argv[1])
    main(n)
我使用CPython和PyPy执行了这段代码,结果如下:

> pypy set.py 100000000
set      : 6.156
frozenset: 6.166

> python set.py 100000000
set      : 16.824
frozenset: 17.248

在CPython和PyPy中,
frozenset
的查找性能实际上较慢。有人知道为什么会这样吗?我没有研究实现。

大部分共享
frozenset
set
实现;
set
只是一个添加了变异方法的
frozenset
,具有完全相同的哈希表实现。看,;顶层与共享功能

这里没有对冻结集进行优化,因为在测试成员资格时,不需要计算
frozenset
中项目的哈希值。用于针对集合进行测试的项仍然需要计算它们的哈希,以便在集合哈希表中找到正确的插槽,以便进行相等性测试

因此,您的计时结果可能由于系统上运行的其他进程而关闭;您测量了挂钟时间,没有禁用Python垃圾收集,也没有重复测试相同的东西

尝试使用运行测试,其中一个值来自
numbers
,另一个不在集合中:

import random
import sys
import timeit

numbers = [random.randrange(sys.maxsize) for _ in range(10000)]
set_ = set(numbers)
fset = frozenset(numbers)
present = random.choice(numbers)
notpresent = -1
test = 'present in s; notpresent in s'

settime = timeit.timeit(
    test,
    'from __main__ import set_ as s, present, notpresent')
fsettime = timeit.timeit(
    test,
    'from __main__ import fset as s, present, notpresent')

print('set      : {:.3f} seconds'.format(settime))
print('frozenset: {:.3f} seconds'.format(fsettime))
每次测试重复100万次,并产生:

set      : 0.050 seconds
frozenset: 0.050 seconds

这两种不同数据类型的原因不是性能,而是功能。因为frozenset是不可变的,所以它们可以在字典中用作键。集合不能用于此目的。

“因为集合是不可变的,因此可以利用存储项的结构”-您希望它做什么?它可以访问的任何结构,
set
也有。这就是我要问的。我想也许frozenset可以使用某种预计算的哈希函数,这反过来可以产生更好的查找性能。您不能在此预计算哈希,因为您可以针对集合测试任意项。我不确定你是如何看待这种优化的?集合中的项不需要计算其散列;它们已经被放入哈希表中。“您需要计算您查找的任何项目的哈希,句号”我知道这一事实,但固定的元素集仍然可以提供优化机会(例如,在生成frozenset时可以生成的完美哈希函数,可用于查找)我同意Sven的观点,通过在创建时进行更多的计算,frozenset理论上可以在查找时执行得更好。例如,对于哈希表实现,可以选择一个哈希函数,以使集合元素的哈希之间的冲突最小。哈希冲突不需要更多内存,它们需要额外的计算。额外内存部分来自哈希表,它预先分配额外内存,以便插入新项。使用frozenset可以避免这两种行为。也可以通过将当前哈希传递给一个无用的修改函数来完成,而无需单独修改每个其他对象的哈希。认为它可能更有效并不是不合理的。@approwme先生:我非常怀疑它会更有效。内存是一次性请求的,计算成本很低,“拟合”表仍然需要哈希计算、模运算和相等性测试。@Mr.shallome:然而,对于一个如此回答的评论线程来说,这一切都变得相当学术和离题。我是否可以建议将这一点引入Python思想,而不是Python核心开发人员所在的位置?无论如何,他们更有资格评估这些想法。请参阅或。