Python,计算计算状态会减慢计算本身

Python, calculating the status of computation slows down the computation itself

这是我所说内容的一个基本示例:

从 0 数到 10000000

import time

k = 0

beginning = time.time()

while k < 10000000:

    k = k+1

elapsed = round(time.time()-beginning, 5)

print (elapsed)

现在有一种 "status" 的计算(每 1 秒显示百分比):

import time

k = 0

beginning = time.time()
interval = time.time()

while k < 10000000:

    if time.time() - interval > 1:
        print (round((k/100000), 5))
        interval = time.time()

    k = k+1

elapsed = round(time.time()-beginning, 5)

print (elapsed)

第一个例子用了 3.67188 秒,第二个例子用了 12.62541 秒。我想那是因为脚本必须不断检查是否已经过了 1 秒。有没有办法解决这个问题?我发现了一些关于线程和多进程的东西,但我不知道如何实现它。谢谢

如果您使用的是类 Unix 系统,则可以使用 signal 模块中的 signal.alarm

下面的代码有点乱,但是你可以通过将东西封装在 class.

中来使它更整洁
import time
import signal

# Alarm delay in seconds. Must be an integer.
alarm_delay = 1

def handler(signum, frame):
    report()

    # Request a new SIGALRM signal
    signal.alarm(alarm_delay)

# Set a handler for the SIGALRM signal
signal.signal(signal.SIGALRM, handler)

# Request the initial SIGALRM signal
signal.alarm(alarm_delay)

# Report current progress
def report():
    print(round(k / 100000, 5))

k = 0
beginning = time.time()
while k < 10000000:
    k = k + 1

elapsed = round(time.time() - beginning, 5)
print (elapsed)

# Cancel the pending alarm
signal.alarm(0)

我的 2GHz 机器上的典型输出

18.90911
35.98427
50.17902
64.53358
83.42723
5.94397

基准测试

我写了不同的解决方案并进行了比较。我需要将您的价值乘以 10 才能获得可衡量的结果。首先没有任何进度测量来查看它 运行 在我的机器上有多快。

def process_without_measuring(self):
    self._start = time.time()

    self._k = 0
    while self._k < 100000000:
        self._k = self._k+1

    print (time.time() - self._start)

我的持续时间为 13.8 秒

让我们从您的实施开始:

def process_with_original_measuring(self):
    self._start = time.time()
    next = self._start
    self._k = 0
    while self._k < 100000000:
        self._k = self._k+1
        if time.time() - next > 1:
            print (round((self._k / 1000000), 5))
            next = time.time()

    print("duration:")
    print (time.time() - self._start)

如果我 运行 这个,我得到 30.31 秒 的持续时间,每秒大约增加 3%。问题是它必须在每个循环 运行d 中比较时间并进行算术运算。您可以通过将循环更改为:

来减少时间
def process_with_manual_measuring(self):
    self._start = time.time()
    next = self._start + 1
    self._k = 0
    while self._k < 100000000:
        self._k = self._k+1
        if time.time() > next:
            print (round((self._k / 1000000), 5))
            next = time.time() + 1

    print("duration:")
    print (time.time() - self._start)

我没有在每个循环中减去时间戳,而是只计算一次下一个时间戳并与它进行比较。这当然不是真的快,但比以前快了。它让我达到 22.0 秒,因此仅通过删除这一操作就节省了 8 秒。

使用计时器对象作为线程可以获得更好的结果,这是更可取的方式:

def show_progress(self):
    print (round((self._k / 1000000), 5))
    self._timer = Timer(1, self.show_progress)
    self._timer.start()

def process_with_timer(self):
    self._start = time.time()
    self._timer = Timer(1, self.show_progress)
    self._timer.start()
    self._k = 0
    while self._k < 100000000:
        self._k = self._k+1
    self._timer.cancel()

    print("duration:")
    print (time.time() - self._start)

运行 这让我每秒多获得 7% 的输出,这是在 13.8 秒 后完成的。如您所见,没有区别。只需要再打几个电话,而且几乎很快就完成了。

如何使用定时器class

Timer 的构造函数需要一个以秒为单位的持续时间和一个在时间结束后调用的方法。您可以使用 class 方法、函数或 lambda 表达式。构建完成后,您需要使用 start().

启动计时器

第一个计时器由进程本身启动。在此之后,每次调用定时器都会启动一个新的定时器以获得一秒的间隔。当该过程完成时,请记得在计时器上调用 cancel()。否则它将 运行 无休止,因为它每秒都会重新启动。

如何运行示例

请注意以上方法是class方法所以注意缩进。

import time
from threading import Timer

class ProgressMeter:
    def __init__(self):
        self._k = 0
        self._timer = 0

    # insert above methods with indentation as same level as __init__(self):

对于运行他们你只需要创建一个 ProgressMeter 的实例并调用你想要的方法。

meter = ProgressMeter()
meter.process_with_timer()