我正在使用线程模块在脚本的其余部分执行时在后台运行功能。线程函数包含一个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限制?
答案 0 :(得分:1)
不幸的是,Python可能无法做得更好。 Python有一个global interpreter lock,这意味着多线程无法像其他语言一样工作。
答案 1 :(得分:1)
您应该意识到python中的多线程会使应用程序运行速度变慢的事实。一个很好的选择是使用asyncio,因为它允许在一个线程内对多个任务进行协作式多任务处理(-> os并不需要实际切换线程->较少的开销->更快的执行)。如果您以前没有使用过它,那么一开始使用起来有点怪异,但实际上真的很好。
但是,您的任务实际上似乎是cpu绑定的。因此,也许唯一的选择是python中的多处理。
答案 2 :(得分:1)
可能不是Python真正的罪魁祸首。关键是,对于一般用途的抢占式多用户操作系统,您将无法保证连续运行足以捕获任何15 ms的触发器。 CPU的分配时间通常为几十毫秒,并且OS可以并且将允许您的线程根据CPU负载或多或少地频繁运行,以努力使每个进程公平分配可用的CPU时间。
您可以增加线程的优先级,以要求其具有其他优先级,或者在极端情况下,将其更改为实时优先级,以使其无限期占用CPU(并可能导致系统挂起)如果东西出错了。
但是,实际上,实际的解决方案是在内核模式或硬件下以较低级别进行处理。如果您不能错过信号,则不建议从用户模式以这些速率进行轮询,因此,您可能应该调查硬件/驱动程序是否提供了更高级别的接口,例如中断(转换为例如解锁某些阻塞调用或产生信号)等等)。