如何减少Python中的线程切换延迟 - python

我有一个Python 2.7应用程序,该应用程序具有连接到Queue.queue的3个生产者线程和1个消费者线程。我正在使用getput,生产者线程将大部分时间都用在IO(从串行端口读取)中阻塞了-基本上什么也不做。基本上调用serial.read() ...

但是,在生产者线程放入队列的时间与消费者线程从队列获取的时间之间,我似乎有一个所谓的高延迟,例如25 ms(我正在运行1个处理器Beagle Bone Black(1GHz )(在Angstrom Linux上)。

我认为,如果所有进程都被阻塞,那么放置和获取之间的经过时间应该非常小,只有几微秒左右,而不是几十毫秒,除非使用者线程实际上很忙(在这种情况下不是这样) )。

我在网上阅读了一些内容,这些内容表明Python犯有忙于旋转的行为,而应归咎于Python中的GIL。我想我宁愿不知道原因,而只是得到一些响应更快的东西。我对串行传输的实际延迟(大约1-2毫秒)很好。

该代码基本上看起来像

q = Queue.queue

def a1(): 
   while True:
      p = read_serial_packet("/dev/ttyO1")
      p.timestamp = time.time()
      q.put(p)

def a2(): 
   while True:
      p = read_serial_packet("/dev/ttyO2")
      p.timestamp = time.time()
      q.put(p)

def a3(): 
   while True:
      p = read_serial_packet("/dev/ttyO3")
      p.timestamp = time.time()
      q.put(p)

def main():
   while True:
      p = q.get()
      d = time.time() - p.timestamp
      print str(d)

并且有4个线程运行a1a2a3main

这是一些采样时间

0.0119640827179
0.0178141593933
0.0154139995575
0.0192430019379
0.0185649394989
0.0225830078125
0.018187046051
0.0234098434448
0.0208261013031
0.0254039764404
0.0257620811462

这是Python 3中“已修复”的东西吗?

参考方案

正如@fileoffset所暗示的,答案似乎是从threading(由于Python GIL实际上并不真正执行“真实”线程)而切换为multiprocessing,后者具有多个python进程而不是线程。

从线程到多处理的转换如下所示:

useMP = True  # or False if you want threading

if useMP:
    import multiprocessing
    import multiprocessing.queues
    import Queue # to import Queue.Empty exception, but don't use Queue.Queue
else:
    import threading
    import Queue

...


    if useMP:
        self.event_queue = multiprocessing.queues.Queue()
        t1 = multiprocessing.Process(target=self.upstream_thread)
        t2 = multiprocessing.Process(target=self.downstream_thread)
        t3 = multiprocessing.Process(target=self.scanner_thread)
    else :
        self.event_queue = Queue.Queue()
        t1 = threading.Thread(target=self.upstream_thread)
        t2 = threading.Thread(target=self.downstream_thread)
        t3 = threading.Thread(target=self.scanner_thread)

该API的其余部分看起来相同。

还有一个重要问题,尽管该问题不容易迁移,但仍作为练习。问题是捕获Unix信号,例如SIGINT或Ctrl-C处理程序。以前,主线程捕获信号,而所有其他线程忽略该信号。现在,信号被发送到所有进程。因此,您必须小心捕获KeyboardInterrupt并安装信号处理程序。我认为我做的方式不正确,所以我不会详细说明... 🙂

Python GPU资源利用 - python

我有一个Python脚本在某些深度学习模型上运行推理。有什么办法可以找出GPU资源的利用率水平?例如,使用着色器,float16乘法器等。我似乎在网上找不到太多有关这些GPU资源的文档。谢谢! 参考方案 您可以尝试在像Renderdoc这样的GPU分析器中运行pyxthon应用程序。它将分析您的跑步情况。您将能够获得有关已使用资源,已用缓冲区,不同渲染状态上…

Python uuid4,如何限制唯一字符的长度 - python

在Python中,我正在使用uuid4()方法创建唯一的字符集。但是我找不到将其限制为10或8个字符的方法。有什么办法吗?uuid4()ffc69c1b-9d87-4c19-8dac-c09ca857e3fc谢谢。 参考方案 尝试:x = uuid4() str(x)[:8] 输出:"ffc69c1b" Is there a way to…

Python sqlite3数据库已锁定 - python

我在Windows上使用Python 3和sqlite3。我正在开发一个使用数据库存储联系人的小型应用程序。我注意到,如果应用程序被强制关闭(通过错误或通过任务管理器结束),则会收到sqlite3错误(sqlite3.OperationalError:数据库已锁定)。我想这是因为在应用程序关闭之前,我没有正确关闭数据库连接。我已经试过了: connectio…

python:ConfigParser对象,然后再阅读一次 - python

场景:我有一个配置文件,其中包含要执行的自动化测试的列表。这些测试是长期循环执行的。   配置文件的设计方式使ConfigParser可以读取它。由于有两个三个参数,因此我需要通过每个测试。现在,此配置文件由script(s1)调用,并且按照配置文件中的列表执行测试。Script(s1)第一次读取配置,并且在每次测试完成后都会执行。阅读两次的要求:由于可能会…

Python exchangelib在子文件夹中读取邮件 - python

我想从Outlook邮箱的子文件夹中读取邮件。Inbox ├──myfolder 我可以使用account.inbox.all()阅读收件箱,但我想阅读myfolder中的邮件我尝试了此页面folder部分中的内容,但无法正确完成https://pypi.python.org/pypi/exchangelib/ 参考方案 您需要首先掌握Folder的myfo…