Python,计算计算状态会降低计算本身的速度

时间:2016-03-04 11:03:55

标签: python performance computation

这是我所谈论的基本例子:

从0到10000000计数

import time

k = 0

beginning = time.time()

while k < 10000000:

    k = k+1

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

print (elapsed)

现在有一种&#34;状态&#34;计算(每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秒。有没有办法解决这个问题?我发现了一些关于线程和多进程的东西,但我无法弄清楚如何实现它。感谢

2 个答案:

答案 0 :(得分:2)

<强>基准

我写了不同的解决方案并进行比较。我需要将您的值乘以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%。问题是它必须比较每个循环rund的时间并进行算术运算。您可以通过将循环更改为:

来缩短时间
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秒之后完成。如你所见,没有区别。只有很少的电话可以制作,而这些电话几乎都可以完成。

如何使用计时器课程

Timer的构造函数需要一个以秒为单位的持续时间和一个经过一段时间后调用的方法。您可以使用类方法,函数或lambda表达式。构建完成后,您需要使用start()启动计时器。

第一个计时器由进程本身启动。在每次定时器调用之后,启动一个新的定时器以获得一秒的间隔。当流程结束时,记得在计时器上调用cancel()。否则它会无止境地运行,因为它会每秒重启一次。

如何运行示例

请注意,上述方法是类方法,因此请注意缩进。

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()

答案 1 :(得分:1)

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

下面的代码有点乱,但是你可以把它封装在一个类中来使它更整洁。

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