我不确定我想做的是有效的做法,但是在这里行得通:
我需要高度并行化我的程序,因此我认为我可以进行2-3个进程,每个进程可以具有2-3个线程。

1)这可能吗?
2)有什么要点吗?
3)这是我的代码,但是当我尝试加入进程时,它挂起了。

PQ = multiprocessing.Queue()

[...]
def node(self, files, PQ):

        l1, l2 = self.splitList(files)
        p1 = multiprocessing.Process(target=self.filePro, args=(l1,PQ,))
        p2 = multiprocessing.Process(target=self.filePro, args=(l2,PQ,))
        p1.daemon = True
        p2.daemon = True
        p1.start()
        p2.start()

        p1.join() # HANGS HERE
        p2.join()
        while 1:
            if PQ.empty():
                break
            else:
                print(PQ.get())
        PQ.join()

    def filePro(self,lst,PQ):
        TQ = queue.Queue()
        l1, l2 = self.splitList(lst)
        t1 = threading.Thread(target=self.fileThr, args=('a',l1,TQ,))
        t2 = threading.Thread(target=self.fileThr, args=('b',l2,TQ,))
        t1.daemon = True
        t2.daemon = True
        t1.start()
        t2.start()

        t1.join()
        t2.join()
        while 1:
            if TQ.empty():
                break
            else:
                PQ.put(TQ.get())
                TQ.task_done()
        TQ.join()

def fileThr(self,id,lst,TQ):
        while lst:
            tmp_path = lst.pop()
            if (not tmp_path[1]):
                continue
            for item in tmp_path[1]:
                TQ.put(1)
        TQ.join()

最佳答案



是的。



是的。但通常不是您要寻找的重点。

首先,几乎每个现代操作系统都使用“固定”调度程序。散布在3个程序中的8个线程或散布在8个程序中的8个线程之间没有区别。*

*在某些您仅知道与同一程序中的线程共享的地方,通过谨慎地使用进程内锁或其他同步原语,某些程序可以显着受益,当然,通过避免在这些地方共享内存,但是您将无法通过在线程之间平均分配工作,并在进程之间平均分配线程来获得 yield 。

其次,即使您在默认的CPython解释器中使用了旧的SunOS,全局解释器锁(GIL)也会确保一次只能有一个线程在运行Python代码。如果您花时间从显式释放GIL的C扩展库中运行代码(例如某些NumPy函数),线程可以提供帮助,但是否则,它们无论如何都最终会序列化。

线程和进程一起使用的主要情况是同时进行CPU绑定(bind)和I/O绑定(bind)。在这种情况下,通常一个人正在喂养另一个人。如果I/O供给CPU,请在主进程中使用单个线程池来处理I/O,然后使用辅助进程池来使CPU对结果进行处理。如果不是这样,请使用工作进程池来执行CPU工作,然后让每个工作进程使用线程池来执行I/O。



如果不提供minimal, complete, verifiable example,则很难调试代码。

但是,我可以看到一个明显的问题。

您正在尝试将TQ用作生产者-消费者队列,将t1t2用作生产者,并将filePro父级用作消费者。您的使用者直到TQ.task_done()t1.join()返回之后才调用t2.join(),直到这些线程完成后才发生。但是这些生产者不会完成,因为他们在等您调用TQ.task_done()。因此,您陷入了僵局。

而且,由于每个子进程的主线程都处于死锁状态,因此它们永远都不会结束,因此p1.join()将永远阻塞。

如果您确实希望主线程在完成其他工作之前一直等到其他线程完成,则不需要生产者-消费者习惯用语。只是让 children 做他们的工作并退出而无需调用TQ.join(),而不必理会 parent 中的TQ.task_done()。 (请注意,您已经使用PQ正确执行了此操作。)

另一方面,如果您希望它们并行工作,则在完成循环之前,请不要尝试对子线程进行join

关于python - Python多处理与多线程结合,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27455155/

10-09 01:59
查看更多