【问题标题】:Python While Loop CPU demandingPython While 循环 CPU 要求高
【发布时间】:2013-02-19 15:55:56
【问题描述】:

我不想用一个简单的问题来打扰这里的人,也不想告诉我我在谷歌上搜索过信息,但我想从面临同样问题的人那里获得意见。据说python中的while循环会减慢(http://wiki.python.org/moin/WhileLoop)。我有一个脚本,它只使用一个循环,但这非常重要,实际上它真的变慢了。我的第一个程序是使用 100% CPU(双核!!!)。我在循环中引入了一个 sleep() 函数,CPU 使用率下降到 50%。我不能一直增加睡眠时间,实际上我想减少它。无论如何,有什么“技巧”可以让这个 while 循环更快吗?

(条件是在pyQt4构建的用户界面上是否按下按钮)

【问题讨论】:

  • 单线程程序在物理上不可能 100% 使用两个内核。其他东西正在使用第二个核心。
  • 我同意。无论如何,很明显这个主 while 循环正在扼杀我的 CPU 使用率。

标签: python-2.7 while-loop


【解决方案1】:

您链接到的参考具有误导性。如果在循环内进行任何实际工作,两个样本之间的速度差异将非常小,通常甚至不明显。

any 循环的本质是它会使用 100% 的分配时间,直到完成。循环是非常有效还是非常低效都没有关系。解决此问题的唯一方法是调用一些使其等待的操作系统函数,例如您尝试过的sleep

现代操作系统 GUI 是事件驱动的原因是,您不必在循环中等待事件 - 您调用单个函数来等待消息,并且操作系统将 CPU 交给其他人,直到一条消息到达。对于像 Qt 这样的框架,这将隐藏在所谓的消息循环中,您需要提供适当的框架挂钩来将事件路由到您自己的函数。

【讨论】:

    【解决方案2】:

    我会研究你给我的信息。但是为了保持讨论,代码的一部分正在变慢:

    while self.startButton.isChecked():
        self.widget.canvas.ax2.clear()                                                 
        self.widget.canvas.ax2.set_xlabel('Sensor #')
        self.widget.canvas.ax2.set_yscale('log', basey = 10)                                   
        self.widget.canvas.ax2.set_xlim(0, num_sensors + 1) 
        self.widget.canvas.ax2.set_xticks(range(1, num_sensors + 1)) 
        self.widget.canvas.ax2.set_xticklabels(sensorLabel, fontsize = 10)
        measure, read_s = [], []                       
        t = round((time() - initialTime), 1)           
        for i in range(num_sensors):
            read = self.ser.readline().strip()  
            measure.append(read)
            read = float(read) 
            read_s.append(read) 
            self.widget.canvas.ax.plot(t, read, plot_array[i])
        self.widget.canvas.ax2.scatter(range(1, num_sensors + 1), read_s, c = log10(read_s), s = 100) 
        self.widget.canvas.ax2.set_ylim(bottom = .8 * min(read_s))                            
        f.write(str(t) + '\t' + '\t'.join(measure) + '\n')  
        self.widget.canvas.ax.legend(loc = 'center left', bbox_to_anchor = (2.2, 0.5), ncol = 1, fontsize = 10)
        self.widget.canvas.draw()                                                       
        QtCore.QCoreApplication.processEvents()                              
        sleep(.5)   # HERE IS THE SLEEP INTRODUCED
    else:
        global last_read     
        last_read = measure   
        self.statusbar.showMessage('Idle')  
        f.close()          
        self.ser.write('C')  
        try:                          
            for i in range(1000):
                self.ser.timeout = .1
                a = self.ser.readline()
                self.statusbar.showMessage('Deleting reads in the serial buffer')  
                if a == 'Last':
                    break 
        except:
            self.ser.close() 
    

    GUI 运行良好(使用少于 2% 的 CPU),直到我在按下 startButton 时调用这部分代码(在我再次按下它之前一直处于选中状态)。

    【讨论】:

    • 只是为了更新线程。我对我的 Ubuntu Linux 运行更新,现在完全相同的程序占用了大约 38% 的 CPU 使用率。谢谢马克的帮助。
    猜你喜欢
    • 1970-01-01
    • 2012-07-20
    • 2018-08-19
    • 2014-11-02
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多