我在timeit上获得了非常令人惊讶的结果,有人可以告诉我我做错了什么吗?我正在使用Python 2.7。
这是文件speedtest_init.py的内容:
import random
to_count = [random.randint(0, 100) for r in range(60)]
这些是speedtest.py的内容:
__author__ = 'BlueTrin'
import timeit
def test_init1():
print(timeit.timeit('import speedtest_init'))
def test_counter1():
s = """\
d = defaultdict(int);
for i in speedtest_init.to_count:
d[i] += 1
"""
print(timeit.timeit(s, 'from collections import defaultdict; import speedtest_init;'))
def test_counter2():
print(timeit.timeit('d = Counter(speedtest_init.to_count);', 'from collections import Counter; import speedtest_init;'))
if __name__ == "__main__":
test_init1()
test_counter1()
test_counter2()
控制台输出为:
C:\Python27\python.exe C:/Dev/codility/chlorum2014/speedtest.py
2.71501962931
65.7090444503
91.2953839048
Process finished with exit code 0
我认为默认情况下timeit()运行代码的1000000倍,因此我需要将时间除以1000000,但是令人惊讶的是Counter的速度比defaultdict()慢。
那是预期的吗?
编辑:
同样,使用dict比defaultdict(int)更快:
def test_counter3():
s = """\
d = {};
for i in speedtest_init.to_count:
if i not in d:
d[i] = 1
else:
d[i] += 1
"""
print(timeit.timeit(stmt=s, setup='from collections import defaultdict; import speedtest_init;')
最后一个版本比defaultdict(int)快,这意味着除非您更关心可读性,否则应使用dict()而不是defaultdict()。
是的,这是预期的;该Counter()
构造
的用途Counter.update()
,它使用self.get()
加载初始值,而不是依靠__missing__
。
此外,defaultdict
__missing__
工厂完全由C代码处理,尤其是在使用其他类似的类型int()
(本身由C实现)时。Counter
源是纯Python,因此该Counter.__missing__
方法需要Python框架才能执行。
由于dict.get()
仍在C中处理,因此对于,构造器方法是更快的方法Counter()
,只要您使用相同的技巧Counter.update()
和别名self.get
作为本地优先项即可:
>>> import timeit
>>> import random
>>> import sys
>>> sys.version_info
sys.version_info(major=2, minor=7, micro=9, releaselevel='final', serial=0)
>>> to_count = [random.randint(0, 100) for r in range(60)]
>>> timeit.timeit('for i in to_count: c[i] += 1',
... 'from collections import Counter; from __main__ import to_count; c = Counter()',
... number=10000)
0.2510359287261963
>>> timeit.timeit('for i in to_count: c[i] = c_get(i, 0) + 1',
... 'from collections import Counter; from __main__ import to_count; c = Counter(); c_get = c.get',
... number=10000)
0.20978617668151855
两者defaultdict
并Counter
为他们的功能,而不是他们的表现内置有用的类; 不依赖__missing__
钩子可以更快:
>>> timeit.timeit('for i in to_count: d[i] = d_get(i, 0) + 1',
... 'from __main__ import to_count; d = {}; d_get = d.get',
... number=10000)
0.11437392234802246
这是使用别名dict.get()
方法以实现最大速度的常规词典。但是随后,您还必须重新实现Counter
或Counter.most_common()
方法的bag行为。该defaultdict
用例去的方式数不胜数。
在Python
3.2中,Counter()
通过添加一个处理这种情况的C库来更新速度。参见问题10667。在Python
3.4上进行测试,Counter()
构造函数现在击败了别名dict.get
情况:
>>> timeit.timeit('Counter(to_count)',
... 'from collections import Counter; from __main__ import to_count',
... number=100000)
0.8332311600097455
>>> timeit.timeit('for i in to_count: d[i] = d_get(i, 0) + 1',
... 'from __main__ import to_count; d = {}; d_get = d.get',
... number=100000)
0.961191965994658
>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=4, micro=2, releaselevel='final', serial=0)
(注意:要获得有意义的计时结果,迭代次数从10k增加到100k;因此,如果将上述dict.get()
情况与上述情况进行比较,则需要在计时中乘以10倍,即1.144秒)。
问题内容: 在我的应用程序中,我遇到了以下问题,并对结果感到惊讶: (两个整数)。 这是什么意思? 问题答案: 对于实际值,即结果为。 您使用整数除法得到的结果将向下舍入为的更负值。(也称为“地板部门”) 这就是为什么您会得到以下令人困惑的答案的原因: 注: 这是在Python 3中,其中的结果,“固定”是。因此,如果您没有理由使用Python 2,则应该升级。;) 在Python 3中,如果仍然
谁能解释一下吗?
问题内容: 我试图弄清楚如何正确使用Java的执行器。我意识到向提交任务有其自身的开销。但是,我惊讶地发现它是如此之高。 我的程序需要以尽可能低的延迟处理大量数据(股市数据)。大多数计算是相当简单的算术运算。 我想测试的东西很简单:“ ” 最简单的测试在一个简单的循环中运行此计算。第二个测试在匿名Runnable内部执行相同的计算(这应该用来衡量创建新对象的成本)。第三次测试将传递给。(这用于衡量
我有一个关于小数的整数的有趣问题。
这是一个来自第三方库API的真实示例,但经过了简化。 用Oracle JDK 8U72编译 考虑以下两种方法: 两者都报告了一个“未经检查的强制转换”警告--我知道原因了。让我困惑的是为什么我可以打电话 试图传递会出现错误,正如所料: 如果报告为错误,为什么不是?