Python中具有多个线程的多个进程

时间:2014-07-30 12:42:43

标签: python multithreading multiprocessing gil

我听说过“如果你想从并行应用程序中获得最大性能,你应该创建与你的计算机有CPU一样多的进程,并在每个进程中创建一些(多少?)线程”。< / p>

是真的吗?

我写了一段实现这个习语的代码:

import multiprocessing, threading

number_of_processes = multiprocessing.cpu_count()
number_of_threads_in_process = 25   # some constant


def one_thread():
    # very heavyweight function with lots of CPU/IO/network usage
    do_main_work()


def one_process():
    for _ in range(number_of_threads_in_process):
        t = threading.Thread(target=one_thread, args=())
        t.start()


for _ in range(number_of_processes):
    p = multiprocessing.Process(target=one_process, args=())
    p.start()

这是对的吗?我的do_main_work函数是否真的并行运行,不会遇到任何GIL问题?

谢谢。

3 个答案:

答案 0 :(得分:2)

# very heavyweight function with lots of CPU/IO/network usage

由于 GIL ,很多 CPU 会受到影响,因此您只能从多个流程中受益。

GIL 网络(实际上网络也是一种IO)不会受到太多影响,因为锁定将在 IO 操作完成后显式释放并再次获取。 CPython中有宏观定义:

Py_BEGIN_ALLOW_THREADS
... Do some blocking I/O operation ...
Py_END_ALLOW_THREADS

由于 GIL 被用于包装代码,但性能仍然受到影响,但您仍然可以通过多个线程获得更好的性能。

最后 - 这是一般规则 - 不仅适用于Python:最佳线程/进程数取决于程序实际执行的操作。通常,如果它集中使用CPU,如果进程数大于CPU核心数,则几乎没有性能提升。例如,Gentoo文档说编译器的最佳线程数是CPU核心+ 1。

答案 1 :(得分:2)

这在很大程度上取决于你正在做什么。

请记住,在CPython中,一次只有一个线程可以执行Python字节码(因为GIL)。因此,对于CPython中的计算密集型问题,线程不会对您有所帮助。

分散可以并行完成工作的一种方法是使用multiprocessing.Pool。默认情况下,这不会使用CPU具有核心的更多进程。使用更多的进程将主要让他们争夺资源(CPU,内存)而不是完成有用的工作。

但是利用多个处理器需要你有工作要做!换句话说,如果问题不能分成可以单独和并行计算的小块,那么许多CPU内核将没有多大用处。

此外,不是问题受到必须进行的计算量的限制。

计算机的RAM比CPU慢得多。如果您正在处理的数据集远大于CPU的缓存,则从RAM中读取数据并将结果返回到RAM可能会成为速度限制。这称为memory bound

如果您正在处理的数据远远超过机器内存中的数据,那么您的程序将从磁盘上进行大量读写操作。与CPU相比,磁盘速度慢,而且与CPU相比,非常慢,因此您的程序变为I/O-bound

答案 2 :(得分:0)

我认为每个进程使用的线程数太高。通常对于任何英特尔处理器,每个进程使用的线程数是2。内核数量从2(Intel core i3)到6(Intel core i7)不等。 )。因此,当所有进程都在运行时,最大线程数将为6 * 2 = 12。