我什么时候应该在常规线程上使用asyncio,为什么?它是否提供了性能提升?

vel*_*bit 27 python multithreading python-asyncio

我对Python中的多线程有一个非常基本的理解,甚至是对它的基本理解asyncio.

我正在编写一个基于Curses的小程序(最终将使用完整的GUI,但这是另一个故事),它处理主线程中的UI和用户IO,然后有另外两个守护程序线程(每个都有自己的队列/工人方法 - 即-得到-东西从 - 一个队列):

  • watcher监视基于时间和条件(例如发布到留言板,收到消息等)事件的线程,然后将所需任务放入...
  • 另一个(worker)守护程序线程的队列然后完成它们.

所有三个线程都在不断地同时运行,这引出了一些问题:

  • worker线程的队列(或者更一般地说,任何线程的队列)为空时,它应该被停止,直到有什么事情要做,或者是否可以继续运行?并发线程在除了查看队列之外没有做任何事情时会占用大量处理能力吗?
  • 这两个线程的队列应该合并吗?由于watcher线程持续运行单个方法,我想worker线程将能够从watcher线程放入的单个队列中拉出任务.
  • 我认为这不重要,因为我不是多处理,但这个设置是否受到Python的GIL(我相信仍然存在于3.4)的影响?
  • 如果该watcher线程连续这样运行?根据我的理解,请纠正我,如果我错了,asyncio应该用于基于事件的多线程,这似乎与我正在尝试做的相关.
  • 主线程基本上只是等待用户按一个键来访问菜单的不同部分.这似乎是一个asyncio完美的情况,但是,我不确定.

谢谢!

dan*_*ano 22

当工作线程的队列(或者更一般地说,任何线程的队列)为空时,它是否应该被停止,直到有再次发生的事情,或者是否可以继续运行?并发线程在除了查看队列之外没有做任何事情时会占用大量处理能力吗?

你应该只使用阻止调用queue.get().这将使线程在I/O上被阻塞,这意味着GIL将被释放,并且将不使用处理能力(或至少非常小的量).不要在while循环中使用非阻塞,因为这将需要更多的CPU唤醒.

这两个线程的队列应该合并吗?由于观察者线程持续运行单个方法,我猜工作线程将能够从观察者线程放入的单个队列中拉出任务.

如果所有观察者正在做的就是从队列中取出并立即将其放入另一个队列中,它被单个工作者消耗掉,这听起来像是不必要的开销 - 您也可以直接在工作中使用它.但是,如果情况确实如此,那么对我来说并不完全清楚 - 观察者是从队列中消费,还是仅仅将物品放入其中?如果从队列中消费,是谁把东西进去?

我认为这不重要,因为我不是多处理,但这个设置是否受到Python的GIL(我相信仍然存在于3.4)的影响?

是的,这受到GIL的影响.只有一个线程可以一次运行Python字节码,因此除非线程正在运行I/O(释放GIL),否则不会获得真正的并行性.如果您的工作线程正在进行CPU绑定活动,那么您应该认真考虑在可能的情况下在单独的进程中运行它multiprocessing.

观察者线程应该像这样连续运行吗?根据我的理解,请纠正我,如果我错了,asyncio应该用于基于事件的多线程,这似乎与我正在尝试做的相关.

很难说,因为我不知道"连续跑"的意思.它在做什么?如果它花费大部分时间睡觉或阻塞a queue,那很好 - 这两件事都释放了GIL.如果它不断地进行实际工作,则需要GIL,因此会降低应用程序中其他线程的性能(假设它们正在尝试同时进行工作).asyncio是为I/O绑定的程序而设计的,因此可以使用异步I/O 在单个线程中运行.听起来你的程序可能非常适合你,这取决于你worker的工作.

主线程基本上只是等待用户按一个键来访问菜单的不同部分.这似乎是asyncio非常适合的情况,但是,我不确定.

任何你大部分都在等待I/O的程序都可能是有用的asyncio- 但是只有你能找到一个能让curses(或者你最终选择的其他GUI库)的库很好地发挥作用.大多数GUI框架都带有自己的事件循环,这将与其冲突asyncio.您需要使用一个库,它可以使GUI的事件循环与事件循环很好地结合使用asyncio.您还需要确保可以找到asyncio应用程序使用的任何其他基于同步I/O的库的兼容版本(例如数据库驱动程序).

也就是说,通过从基于线程的程序切换到基于程序的程序,您不太可能看到任何性能提升asyncio.它的表现可能大致相同.由于您只处理3个线程,因此它们之间的上下文切换开销并不是很重要,因此从单线程异步I/O方法切换不会产生很大的差异.asyncio将帮助您避免线程同步复杂性(如果这是您的应用程序的一个问题 - 它不清楚它是什么),并且至少在理论上,如果您的应用程序可能需要大量的线程,它会更好地扩展,但它似乎不是那样的案件.我认为对你来说,这基本上取决于你喜欢编写哪种风格(假设你可以找到所需的所有asyncio兼容的库).