【问题标题】:Thread does not run fast enough when other applications are running其他应用程序运行时线程运行速度不够快
【发布时间】:2019-04-19 15:23:02
【问题描述】:

我正在使用线程模块在后台运行一个函数,同时执行我的脚本的其余部分。线程函数包含一个 for 循环,该循环等待外部 5 伏触发器,每 15 毫秒发生一次,然后继续下一个循环迭代。

当此代码是唯一在 PC 上运行的代码时,一切都会按预期运行。但是,当我运行其他必要的应用程序时,给 cpu 带来压力时,线程函数中的 For 循环仅在大约 90% 的时间内执行并在 15 毫秒的时间窗口内继续进行下一次迭代。

线程函数的输入是一个 ctypes 指针列表。

我在一个类中运行线程函数,所以使用多处理很棘手(我不确定这是否有帮助)。

我试图用两个类的骨架来说明下面的问题

import ctypes
import Write_transient_frames_func
import SendScriptCommands
from threading import Thread

class SlmInterface():

    def __init__(self,sdk):

        self.sdk = sdk

    def precalculate_masks(self, mask_list):

        '''takes input mask_list, a list of numpy arrays containing phase masks
           outputs pointers to memory location of masks
        '''

        #list of pointers to locations of phase mask arrays in memory 
        mask_pointers = [mask.ctypes.data_as(POINTER(c_ubyte)) for mask in mask_list]

        return mask_pointers

    def load_precalculated_triggered(self, mask_pointers):

        okay = True
        print('Ready to trigger')

        for arr in mask_pointers:

            okay = self.Write_transient_frames_func(self.sdk, c_int(1), arr, c_bool(1), c_bool(1), c_uint(0))

        assert okay, 'Failed to write frames to board'      
        print('completed trigger sequence')


class Experiment():

    def run_experiment(self, sdk, mask_list):  

        slm = SlmInterface(sdk)

        #list of ctypes pointers      
        mask_pointers = slm.precalculate_masks(mask_list)

        ##the threaded function
        slm_thread = Thread(target=slm.load_precalculated_triggered, args = [mask_pointers])
        slm_thread.start()

        time.sleep(0.1)

        # this function loads the 15ms trigger sequences to the hardware and begins the sequence 
        self.mp_output = SendScriptCommands()

是否可以加快线程函数的执行速度?并行处理会有帮助吗?还是我从根本上受限于我的 CPU?

【问题讨论】:

  • 您正在使用并行处理。线程在操作系统的控制之下。我认为您对 15 毫秒响应时间的要求是不现实的。
  • 谢谢,是否有替代方案可以让我在后台运行 load_precalculated_triggered 函数,然后继续执行脚本的其余部分?
  • 我之前也遇到过同样的问题,发现我的线程有while循环运行并消耗cpu功率,后来我发现我必须添加'time.sleep(0.1)'作为延迟循环内的时间给另一个线程工作的时间,令人惊讶的是,我的 cpu 使用率正常,线程运行速度超快,注意:我的应用程序是一个下载管理器,它在一次下载中生成 100 多个并发线程,并且可以在同时没有速度下降
  • 在试图捕获每 15 毫秒发生一次的信号的线程中休眠 100 毫秒只会使问题变得更糟。现在你每 6 次丢失约 5 个信号 - 干得好!

标签: python python-multiprocessing python-multithreading


【解决方案1】:

不幸的是,Python 可能无法做得更好。 Python 有一个global interpreter lock,这意味着多线程不像其他语言那样工作。

【讨论】:

    【解决方案2】:

    您应该知道,python 中的多线程会使应用程序运行得更慢。一个不错的选择是使用 asyncio,因为它允许在一个线程中协同多任务处理多个任务(-> 操作系统不需要实际切换线程-> 更少的开销-> 更快的执行)。如果你之前没有使用过它,一开始会觉得有点奇怪,但它实际上真的很好。

    但是,您的任务似乎确实受 CPU 限制。所以也许唯一的选择是 python 中的多处理。

    【讨论】:

      【解决方案3】:

      可能 Python 并不是真正的罪魁祸首。关键是,对于通用、抢占式、多用户操作系统,您无法保证连续运行足以捕获任何 15 毫秒的触发器。 CPU 通常以几十毫秒的数量分配,并且操作系统可以 - 并且将 - 让您的线程根据 CPU 负载或多或少地运行,以努力为每个进程提供公平的可用 CPU 时间份额。

      您可以增加线程的优先级以要求它优先于其他线程,或者在极端情况下,将其更改为实时优先级以使其无限期地占用 CPU(并可能挂起系统如果出现问题)。

      但实际上,真正的解决方案是在较低级别处理这个问题,无论是在内核模式还是在硬件中。如果您不能错过信号,则不建议从用户模式以这些速率进行轮询,因此您可能应该调查您的硬件/驱动程序是否提供了一些更高级别的接口 - 例如,中断(例如转换为解锁某些阻塞调用或产生信号或其他东西)触发。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-07
        相关资源
        最近更新 更多