为什么我的Python版本比Perl版本慢?[closed]

ccrfmcuu  于 2023-01-04  发布在  Python
关注(0)|答案(9)|浏览(115)

很难判断此处所问的问题。此问题模棱两可、模糊不清、不完整、过于宽泛或过于修辞,无法以其当前形式合理地回答。若要获得澄清此问题以便重新打开的帮助,请单击visit the help center
13年前就关闭了。
我使用Perl已经超过10年了,但是一个朋友说服我尝试Python,告诉我Python比Perl快很多。所以为了好玩,我把一个用Perl编写的应用程序移植到Python上,发现它运行起来慢了3倍。最初我的朋友告诉我,我一定是做错了。所以我重写和重构直到我不能再重写和重构了......它还是慢了很多。所以我做了一个简单的测试:

i = 0
j = 0

while (i < 100000000):
    i = i + 1
    j = j + 1

print j

$ time Pythonpython.py
100000000
真实的0m48.100s
用户0m45.633s
系统0m0.043s

my $i = 0;
my $j = 0;

while ($i < 100000000) {
    ++$i; # also tested $i = $i + 1 to be fair, same result
    ++$j;
}

print $j;

$ time Perlperl.pl
100000000
真实的0m24.757s
用户0m22.341s
系统0m0.029s
慢了不到两倍,这似乎没有反映出我所看到的任何基准测试......是我的安装有问题还是 * Python真的比Perl慢那么多 *?

ykejflvf

ykejflvf1#

吹毛求疵的答案是,你应该将它与惯用Python进行比较:

  • 原始代码在我的机器上需要34秒。
  • 包含+=xrange()for循环(FlorianH's answer)需要21
  • 把整个事情放在一个函数中可以减少到9秒!
    • 这比Perl快多了**(在我的机器上只需15秒)!

说明:Python局部变量比全局变量快得多。
(For公平,我也尝试了Perl中的一个函数-没有变化)

  • 去掉j变量后,时间缩短为8秒:

print sum(1 for i in xrange(100000000))
Python有一个奇怪的特性,即较高级的较短代码往往速度更快:-)
但真正的答案是,你的"微标杆"毫无意义,语言速度的真正问题是:一个真实应用程序的平均性能是多少?要了解这一点,您应该考虑:

  • 复杂代码中的典型混合操作。您的代码不包含任何数据结构、函数调用或OOP操作。
  • 一个足够大的代码库来感受缓存效应--许多解释器优化用内存来换取速度,而这是任何微小的基准测试都无法公平衡量的。
  • Optimizationopportunities:在你写好代码之后,如果它还不够快,你能轻松地使它快多少呢?

把繁重的工作交给高效的图书馆有多难?
PyPy's benchmarksOctane是真实语言速度基准测试的良好示例。
如果你想谈论数字运算,Python**在科学家中的流行程度令人惊讶。他们喜欢Python *,因为它具有简单的伪数学语法和较短的学习曲线,而且它还具有出色的numpy数组运算库,并且易于 Package 其他现有的C代码。
还有Psyco JIT,它可能会在1秒内运行您的玩具示例,但我现在无法检查它,因为它只适用于32位x86。

  • 编辑 *:现在,跳过Psyco,使用PyPy,它是一个跨平台的、积极改进JIT的工具。
3pvhb19x

3pvhb19x2#

所有这些微观基准测试可能会变得有点愚蠢!
例如,在Python和Perl中切换到for会带来很大的减速,如果使用for,原来的Perl示例会快两倍:

my $j = 0;

for my $i (1..100000000) {
    ++$j;
}

print $j;

我可以用这个多刮一点:

++$j for 1..100000000;
print $j;

更傻的是,我们可以把它降到1秒; -)

print {STDOUT} (1..10000000)[-1];

/I3az/

  • 参考 *:使用Perl 5.10.1。
eni9jsuy

eni9jsuy3#

Python运行速度非常快,如果你使用正确的Python语言语法的话。它被粗略地描述为“pythonic“。
如果你像这样重新构造你的代码,它的运行速度至少会提高一倍(在我的机器上确实如此):

j = 0
for i in range(10000000):
    j = j + 1
print j

无论何时在Python中使用while,都应该检查是否还可以使用“for X in range()"。

ogsagwnx

ogsagwnx4#

python在数值计算方面不是特别快,我敢肯定在文本处理方面它比perl慢。
既然你是一个有经验的Perl高手,我不知道这是否适用于你,但从长远来看,Python程序往往更容易维护,开发速度更快。速度对大多数情况来说"足够"了,当你 * 真的 * 需要提高性能时,你可以灵活地转向C语言。

更新

好的。我刚刚创建了一个大文件(1GB),里面有随机数据(大部分是ASCII),并把它分成等长的行。这应该是模拟一个日志文件。
然后我运行简单的perl和python程序,逐行搜索文件中的现有模式。
在Python 2.6.2中,结果为

real    0m18.364s
user    0m9.209s
sys 0m0.956s

以及Perl 5.10.0

real    0m17.639s
user    0m5.692s
sys 0m0.844s

程序如下(如果我做了什么蠢事,请告诉我)

import re
regexp = re.compile("p06c")

def search():
    with open("/home/arif/f") as f:
        for i in f:
            if regexp.search(i):
                print "Found : %s"%i

search()

以及

sub search() {
  open FOO,"/home/arif/f" or die $!;
  while (<FOO>) {
    print "Found : $_\n" if /p06c/o;
  }
}

search();

结果非常接近,这样或那样的调整似乎不会改变结果。我不知道这是否是一个 * 真正的 * 基准,但我认为这将是我在这两种语言中搜索日志文件的方式,所以我站在相对性能更正。
谢谢克里斯。

i2loujxw

i2loujxw5#

对于OP,Python中的这段代码:

j = 0
for i in range(10000000):
    j = j + 1
print j

等于

print range(10000001)[-1]

在我的机器上

$ time python test.py
10000000

real    0m1.138s
user    0m0.761s
sys     0m0.357s

range()(或xrange)是Python的内部函数,它已经可以为你生成一个数字序列。因此,你不需要使用自己的循环来创建自己的迭代。现在,你可以找到一个Perl等价函数,它可以运行1秒来产生相同的结果

6l7fqoea

6l7fqoea6#

Python在字典中维护全局变量,因此,每次有赋值语句时,解释器都会在模块字典上执行一次查找,这是比较昂贵的,这也是为什么你发现你的例子很慢的原因。
为了提高性能,你应该使用局部分配,就像创建一个函数一样。Python解释器将局部变量存储在一个数组中,访问速度要快得多。
不过需要注意的是,这是CPython的一个实现细节;例如,我怀疑IronPython会导致完全不同的结果。
最后,为了获得关于这个主题的更多信息,我推荐一篇来自GvR的有趣文章,关于Python中的优化:Python Patterns - An Optimization Anecdote.

wfypjpf4

wfypjpf47#

python比perl慢。它可能开发得更快,但执行得并不快。这里有一个基准测试http://xodian.net/serendipity/index.php?/archives/27-Benchmark-PHP-vs.-Python-vs.-Perl-vs.-Ruby.html-edit-一个糟糕的基准测试,但它至少是一个真正的数字基准测试,而不是一些猜测。糟糕的是,除了循环之外,没有源代码或测试。

3qpi33ja

3qpi33ja8#

我并不是对Python的所有方面都很了解,但我对这个基准测试的第一个想法是Perl和Python数字之间的区别。在Perl中,我们有数字。它们不是对象,它们的精度受限于体系结构所施加的大小。在Python中,我们有任意精度的对象。对于较小的数字(那些适合32位的),我希望Perl更快,如果我们超过架构的整数大小,Perl脚本甚至不做一些修改就不能工作。
在我的MacBook Air(32位)上,使用我自己编译的Perl 5.10.1和Leopard附带的Python 2.5.1,我看到了类似的原始基准测试结果:
但是,我使用bignum向Perl程序添加了任意精度

use bignum;

现在我想知道Perl版本是否会完成。:)当它完成时,我会发布一些结果,但看起来这将是一个数量级的差异。
你们中的一些人可能已经看到了我关于What are five things you hate about your favorite language?的问题。Perl的默认数字是我讨厌的事情之一。我不应该去想它,它也不应该很慢。在Perl中,我在这两方面都输了。但是请注意,如果我需要在Perl中进行数字处理,我可以使用PDL

kmpatx3s

kmpatx3s9#

Python真的比Perl慢那么多吗
看看计算机语言基准测试游戏-“使用约12个有缺陷的基准测试和约1100个程序比较约30种编程语言的性能”。
它们只是很小的基准测试程序,但它们所做的工作仍然比您计时的代码片段要多得多-
http://shootout.alioth.debian.org/u32/python.php

相关问题