当其他应用程序正在运行时,线程运行速度不够快

时间:2019-04-19 15:23:02

标签: python python-multiprocessing python-multithreading

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

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

线程函数的输入是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限制?

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

您应该意识到python中的多线程会使应用程序运行速度变慢的事实。一个很好的选择是使用asyncio,因为它允许在一个线程内对多个任务进行协作式多任务处理(-> os并不需要实际切换线程->较少的开销->更快的执行)。如果您以前没有使用过它,那么一开始使用起来有点怪异,但实际上真的很好。

但是,您的任务实际上似乎是cpu绑定的。因此,也许唯一的选择是python中的多处理。

答案 2 :(得分:1)

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

您可以增加线程的优先级,以要求其具有其他优先级,或者在极端情况下,将其更改为实时优先级,以使其无限期占用CPU(并可能导致系统挂起)如果东西出错了。

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