2016-03-04 141 views
5

这是什么我谈论的是一个基本的例子:Python中,计算计算的状态减慢计算本身

计数从0〜10000000

import time 

k = 0 

beginning = time.time() 

while k < 10000000: 

    k = k+1 

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

print (elapsed) 

现在带有几分“计算(百分比显示每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秒。有没有办法解决这个问题?我发现了一些线程和多进程,但我无法弄清楚如何实现它。谢谢

+0

没有试过这个实现,但会像这样的工作? https://docs.python.org/2/library/threading.html#timer-objects – Tom

+0

也许你可以将计算包装到某种“Task”类中,并让另一个线程定期检查该任务的状态。虽然有点模糊。 –

+0

取决于处理器。你有多少核心?我试图第二个例子上一个imac,它显示输出'39.0 79.0 2.53144' 我想这花了2.53s – pbu

回答

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百分比高达每秒的持续时间。问题是它必须比较每一个循环的时间,并进行一次算术运算。

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类

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

对不起,这可能是一个愚蠢的问题,但我该如何运行它? – Matteo

+0

不错,我会稍后再试,并提供反馈,谢谢 – Matteo

+0

我会很感激一些反馈意见。 – DreyFax

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