python - 可以在纯 Python 中加速这个循环吗?

标签 python testing performance timing

我正在尝试使用 Python 进行实验,试图找出它可以在一分钟内将整数加一多少次。假设两台计算机除了 CPU 的速度之外是相同的,这应该可以估计某些 CPU 操作对于相关计算机可能需要多快。

下面的代码是为满足上述要求而设计的测试示例。这个版本比第一次尝试快 20%,比第三次尝试快 150%。任何人都可以就如何在一分钟内获得最多的添加提出任何建议吗?更高的数字是可取的。

编辑 1:这个实验是用 Python 3.1 编写的,比第四次加速尝试快 15%。

def start(seconds):
    import time, _thread
    def stop(seconds, signal):
        time.sleep(seconds)
        signal.pop()
    total, signal = 0, [None]
    _thread.start_new_thread(stop, (seconds, signal))
    while signal:
        total += 1
    return total

if __name__ == '__main__':
    print('Testing the CPU speed ...')
    print('Relative speed:', start(60))

编辑 2: 关于在 while 循环中使用 True 而不是 1:应该没有速度差异。下面的实验证明它们是一样的。首先,创建一个名为 main.py 的文件并将以下代码复制到其中。

def test1():
    total = 0
    while 1:
        total += 1

def test2():
    total = 0
    while True:
        total += 1

if __name__ == '__main__':
    import dis, main
    dis.dis(main)

运行代码应该会产生以下输出,显示代码的实际编译方式以及生成的 Python 虚拟机指令 结果是什么。

Disassembly of test1:
  2           0 LOAD_CONST               1 (0) 
              3 STORE_FAST               0 (total) 

  3           6 SETUP_LOOP              13 (to 22) 

  4     >>    9 LOAD_FAST                0 (total) 
             12 LOAD_CONST               2 (1) 
             15 INPLACE_ADD          
             16 STORE_FAST               0 (total) 
             19 JUMP_ABSOLUTE            9 
        >>   22 LOAD_CONST               0 (None) 
             25 RETURN_VALUE         

Disassembly of test2:
  7           0 LOAD_CONST               1 (0) 
              3 STORE_FAST               0 (total) 

  8           6 SETUP_LOOP              13 (to 22) 

  9     >>    9 LOAD_FAST                0 (total) 
             12 LOAD_CONST               2 (1) 
             15 INPLACE_ADD          
             16 STORE_FAST               0 (total) 
             19 JUMP_ABSOLUTE            9 
        >>   22 LOAD_CONST               0 (None) 
             25 RETURN_VALUE         

发出的 PVMI(字节码)完全相同,因此两个循环的运行速度应该没有任何差异。

最佳答案

我看到与 the @Amber's one 几乎相同但始终更好 (~2%) 的结果在 my machine在 Python 3.1.2 上的代码:

import signal

class Alarm(Exception):
    pass

def alarm_handler(signum, frame):
    raise Alarm

def jfs_signal(seconds):
    # set signal handler
    signal.signal(signal.SIGALRM, alarm_handler)
    # raise Alarm in `seconds` seconds
    signal.alarm(seconds)

    total = 0
    try:
        while 1:
            total += 1
    finally:
        signal.alarm(0) # disable the alarm
        return total

这是使用 subprocess 模块运行可中断循环的变体:

#!/usr/bin/env python
# save it as `skytower.py` file
import atexit
import os
import signal
import subprocess
import sys
import tempfile
import time

def loop():
    @atexit.register
    def print_total():
        print(total)

    total = 0
    while 1:
        total += 1

def jfs_subprocess(seconds):
    # start process, redirect stdout/stderr
    f = tempfile.TemporaryFile() 
    p = subprocess.Popen([sys.executable, "-c",
                          "from skytower import loop; loop()"],
                         stdout=f, stderr=open(os.devnull, 'wb'))
    # wait 
    time.sleep(seconds)

    # raise KeyboardInterrupt
    #NOTE: if it doesn't kill the process then `p.wait()` blocks forever
    p.send_signal(signal.SIGINT) 
    p.wait() # wait for the process to terminate otherwise the output
             # might be garbled

    # return saved output
    f.seek(0) # rewind to the beginning of the file
    d = int(f.read())
    f.close()
    return d

if __name__ == '__main__':
    print('total:', jfs_subprocess(60))

它比我机器上的 signal.alarm() 变体慢 ~20%。

关于python - 可以在纯 Python 中加速这个循环吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4676544/

相关文章:

c# - 基于nlog输出的功能测试

bash - 测试编译代码以返回预期输出/错误的最佳方法

c - 是否像在 JavaScript 中一样,在 C 中创建函数会导致性能下降?

c++ - 如何加速 dijkstra 单源、单目标回溯?

python - 如何格式化 url 以在模板中返回类似 "product/4/improved-led-lamp"的内容

python - 将 python 输出格式化为 json

python - 总结字典中的值(Python 方式)

api - 测试调用相同私有(private)方法的多个公共(public)方法

sql - 如何优化查询以计算行相关的日期时间关系?

python - 改进SQL INSERT查询以避免sql注入(inject)