V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
simon4545
V2EX  ›  Python

python 纯加减运算慢

  •  
  •   simon4545 · 2016-04-02 14:28:46 +08:00 · 5280 次点击
    这是一个创建于 3162 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Python 代码: import time a=time.time() i=0 for i in xrange(95550000): i +=100 i -=100 print i print time.time()-a

    运行结果: 95549999 15.253000021

    得到的不是 95550000 编译成了 Pyc 也一样的结果

    但换成 Node.js 会快 100 倍都不止 var a=new Date(); var i; for(i = 0; i < 95550000; ++i) {    i += 100; i -= 100; } console.log(i) console.log((new Date())-a)

    结果: 95549999 0.21799993515

    我试了 pypy,性能和 node.js 接近

    28 条回复    2016-04-04 13:46:05 +08:00
    koykoi
        1
    koykoi  
       2016-04-02 15:01:29 +08:00
    这种 hot spot 代码不正是 JIT 的优势吗
    clino
        2
    clino  
       2016-04-02 15:17:23 +08:00
    nodejs 应该和 pypy 一样都用了 jit 吧?
    clino
        3
    clino  
       2016-04-02 15:26:31 +08:00
    我这里的结果是
    -在循环里算两个+-耗时 15.1 秒
    -在循环里算一个+耗时 9.89 秒
    -循环里 pass 耗时 3.72 秒
    BOYPT
        4
    BOYPT  
       2016-04-02 15:27:47 +08:00
    大概是因为 python 里面的整数是 immutable 的对象,你这样的操作就是重复生成对象和回收对象,所以效率较低;大概使用 numbers 模块里面功能会有改善。
    josephok
        5
    josephok  
       2016-04-02 16:01:50 +08:00
    用 python3 试试
    zwpaper
        6
    zwpaper  
       2016-04-02 16:09:22 +08:00
    本来就应该是 9554999 的吧?
    python3 是:
    95549999
    10.84103798866272
    Zzzzzzzzz
        7
    Zzzzzzzzz  
       2016-04-02 16:09:46 +08:00
    光这个 xrange 就得两三秒.
    要改进性能的话把这段代码抽出来上 Cython , i = 0 前面加 cdef long, 秒变毫秒级.
    simon4545
        8
    simon4545  
    OP
       2016-04-02 16:18:36 +08:00
    python3 执行也是一样的,而且还要更久一点
    有没有 jit 居然相差那么大
    realpg
        9
    realpg  
       2016-04-02 19:15:31 +08:00   ❤️ 1
    1. python 内 xrange(3)的结果是 0,1,2
    2. 这种场景就是 JIT 的性能强悍啊

    realpg@TestingServer17:/tmp/demo$ python python.py
    95549999
    15.7798058987
    realpg@TestingServer17:/tmp/demo$ pypy python.py
    95549999
    0.574637174606
    realpg@TestingServer17:/tmp/demo$ /usr/local/php5/bin/php php.php
    95550000
    7.9244079589844
    realpg@TestingServer17:/tmp/demo$ /usr/local/php7/bin/php php.php
    95550000
    3.8246450424194


    python2.7 python.py 代码同楼主

    php.php 代码
    <?php
    $time_start = microtime(true);
    for ($i=0;$i<95550000;$i++) {
    $i+=100;
    $i-=100;
    }
    $time_end = microtime(true);
    $time = $time_end - $time_start;
    echo "{$i}\n{$time}\n";
    slixurd
        10
    slixurd  
       2016-04-02 19:21:49 +08:00
    居然连 microbench 之类的工具都没用,在这裸写。。。。
    bigtan
        11
    bigtan  
       2016-04-02 19:24:52 +08:00   ❤️ 2
    用 Python ,执行效率一般难以成为瓶颈,因为,他可以通过别的优化手段轻松的达到 C-level 的执行效率。
    theoractice
        12
    theoractice  
       2016-04-02 20:27:43 +08:00
    @bigtan 42.7ns ?表示震惊
    zhuangzhuang1988
        13
    zhuangzhuang1988  
       2016-04-02 22:01:59 +08:00
    没 jit 就得这么慢, 虽然里面有一些 intern 缓存优化。但是对这些纯计算的没啥鸟用。。
    bigtan
        14
    bigtan  
       2016-04-02 22:04:09 +08:00
    @theoractice 有缓存的可能,你可以看 best case 。 42.7ns*24.87=1061.9ns ,不过也足够惊人的了。
    est
        15
    est  
       2016-04-02 22:21:06 +08:00
    其实 python 加减乘除不慢, for 比较慢。
    mathgl
        16
    mathgl  
       2016-04-02 22:30:28 +08:00
    这种代码, jit 稍微优化一下就是常数了。
    Zzzzzzzzz
        17
    Zzzzzzzzz  
       2016-04-02 22:37:08 +08:00
    @theoractice
    @bigtan

    倒没那么夸张, Cython 现在对 range 和 xrange 有优化, 会直接转成循环, 以前那种 for i from 0<=i<95550000 的方言被废了, 然后默认的编译参数又是-O2, 直接把循环这部分给优化掉了,等于什么都没做直接给 i 赋值了
    SlipStupig
        18
    SlipStupig  
       2016-04-03 01:35:18 +08:00
    每次+一次就是内存申请一次啊,而且你用 for 就变成了直接 sum 回快多了 sum(xrange(95550000)),时间明显减少太多了

    3 function calls in 1.140 seconds

    Ordered by: standard name

    ncalls tottime percall cumtime percall filename:lineno(function)
    1 0.000 0.000 1.140 1.140 test.py:1(<module>)
    1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
    1 1.140 1.140 1.140 1.140 {sum}
    simon4545
        19
    simon4545  
    OP
       2016-04-03 02:47:55 +08:00
    @est 我后面也试了,正如你所说的一样。
    能请教一下原因么?
    pynix
        20
    pynix  
       2016-04-03 04:27:50 +08:00
    不可变对象,一直在申请和释放内存。
    imn1
        21
    imn1  
       2016-04-03 10:44:45 +08:00
    @simon4545
    while 也比 for 快一点
    python 官方都建议用列表 /元组表达式代替 for 循环优化
    simon4545
        22
    simon4545  
    OP
       2016-04-03 11:40:57 +08:00
    @imn1 python 我是新手,你说的列表元组是指的是用[sum(x ) for i in range(59990000)]推导么?
    imn1
        23
    imn1  
       2016-04-03 12:37:03 +08:00
    @simon4545
    (x for x in ...)
    [x for x in ...]
    wizardforcel
        24
    wizardforcel  
       2016-04-03 12:55:30 +08:00 via Android
    node 自带了 jit ,你用 xpcshell 试试。(逃
    fullpowers
        25
    fullpowers  
       2016-04-03 14:23:34 +08:00 via Android
    我智商捉急,求问为什么是 95549999
    zonghua
        26
    zonghua  
       2016-04-03 14:54:23 +08:00 via iPhone
    @bigtan 我想深入了解一下 cython
    MrEggNoodle
        27
    MrEggNoodle  
       2016-04-03 15:54:51 +08:00
    @bigtan 看到你这个,我决定深入了解一下 cython 了。
    simon4545
        28
    simon4545  
    OP
       2016-04-04 13:46:05 +08:00
    +1 cython
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1256 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 18:17 · PVG 02:17 · LAX 10:17 · JFK 13:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.