简体   繁体   English

为什么多处理的每个进程开销不断增加?

[英]Why does per-process overhead constantly increase for multiprocessing?

I was counting for a 6 core CPU with 12 logical CPUs in a for-loop till really high numbers several times.我数次在 for 循环中计算一个 6 核 CPU 和 12 个逻辑 CPU,直到非常高的数字。

To speed things up i was using multiprocessing.为了加快速度,我使用了多处理。 I was expecting something like:我期待类似的东西:

  • Number of processes <= number of CPUs = time identical进程数 <= CPU 数 = 时间相同
  • number of processes + 1 = number of CPUs = time doubled进程数 + 1 = CPU 数 = 时间加倍

What i was finding was a continuous increase in time.我发现的是时间的持续增加。 I'm confused.我很困惑。

the code was:代码是:

#!/usr/bin/python

from multiprocessing import Process, Queue
import random
from timeit import default_timer as timer

def rand_val():
    num = []
    for i in range(200000000):
        num = random.random()
    print('done')

def main():

    for iii in range(15):
        processes = [Process(target=rand_val) for _ in range(iii)]
        start = timer()
        for p in processes:
            p.start()

        for p in processes:
            p.join()

        end = timer()
        print(f'elapsed time: {end - start}')
        print('for ' + str(iii))
        print('')

if __name__ == "__main__":
    main()
    print('done')

result:结果:

  • elapsed time: 14.9477102 for 1经过时间:14.9477102 为 1
  • elapsed time: 15.4961154 for 2经过时间:15.4961154 为 2
  • elapsed time: 16.9633134 for 3经过时间:16.9633134 为 3
  • elapsed time: 18.723183399999996 for 4经过时间:18.723183399999996 为 4
  • elapsed time: 21.568377299999995 for 5经过时间:21.568377299999995 为 5
  • elapsed time: 24.126758499999994 for 6经过时间:24.126758499999994 为 6
  • elapsed time: 29.142095499999996 for 7经过时间:29.142095499999996 为 7
  • elapsed time: 33.175509300000016 for 8经过时间:33.175509300000016 为 8

. . . . . .

  • elapsed time: 44.629786800000005 for 11经过时间:11 为 44.629786800000005
  • elapsed time: 46.22480710000002 for 12经过时间:12 为 46.22480710000002
  • elapsed time: 50.44349420000003 for 13经过时间:13 为 50.44349420000003
  • elapsed time: 54.61919949999998 for 14经过时间:54.61919949999998 为 14

I don't understand what you are trying to achieve?我不明白你想要达到什么目的?

You are taking the same work, and running it X times, where X is the number of SMPs in your loop.您正在进行相同的工作,并运行 X 次,其中 X 是循环中 SMP 的数量。 You should be taking the work and dividing it by X, then sending a chunk to each SMP unit.您应该将工作除以 X,然后将一个块发送到每个 SMP 单元。

Anyway, with regards what you are observing - you are seeing the time it takes to spawn and close the separate processes.无论如何,关于您正在观察的内容 - 您会看到生成和关闭单独进程所需的时间。 Python isn't quick at starting new processes. Python 无法快速启动新流程。

There are two wrong assumptions you make:你有两个错误的假设:

  1. Processes are not free.流程不是免费的。 Merely adding processes adds overhead to the program.仅仅添加进程会增加程序的开销。
  2. Processes do not own CPUs.进程不拥有 CPU。 A CPU interleaves execution of several processes. CPU 交错执行多个进程。

The first point is why you see some overhead even though there are less processes than CPUs.第一点是为什么您会看到一些开销,即使进程少于 CPU。 Note that your system usually has several background processes running, so the point of "less processes than CPUs" is not clearcut for a single application.请注意,您的系统通常有多个后台进程正在运行,因此对于单个应用程序来说,“进程少于 CPU”这一点并不明确。

The second point is why you see the execution time increase gradually when there are more processes than CPUs.第二点是为什么当进程多于 CPU 时执行时间会逐渐增加。 Any OS running mainline Python does preemptive multitasking of processes ;任何运行主线 Python 的操作系统都会对进程进行抢占式多任务处理 roughly, this means a process does not block a CPU until it is done, but is paused regularly so that other processes can run.粗略地说,这意味着一个进程在完成之前不会阻塞 CPU,而是定期暂停,以便其他进程可以运行。
In effect, this means that several processes can run on one CPU at once.实际上,这意味着多个进程可以同时在一个 CPU 上运行。 Since the CPU can still only do a fixed amount of work per time, all processes take longer to complete.由于 CPU 每次仍然只能完成固定数量的工作,因此所有进程都需要更长的时间才能完成。

Your test is faulty.你的测试有问题。

Imagine this, it takes 1 day for one farmer to work a 10km^2 farmland using a single tractor.想象一下,一个农民用一台拖拉机耕种 10km^2 的农田需要 1 天时间。 If there are two farmers working 20km^2 farms, why are you expecting two farmers working twice the amount of farmlands using two tractors to take less time?如果有两个农民在 20 公里^2 的农场工作,你为什么期望两个农民使用两台拖拉机在两倍的农田上工作花费更少的时间?

You have 6 CPU cores, your village has 6 tractors, but nobody has money to buy private tractors.你有 6 个 CPU 核心,你的村庄有 6 辆拖拉机,但没有人有钱购买私人拖拉机。 As the number of workers (processes) on the village increased, the number of tractors remain the same, so everyone has to share the limited number of tractors.随着村里工人(工序)数量的增加,拖拉机的数量保持不变,所以每个人都必须分享有限数量的拖拉机。

In an ideal world, two farmers working twice the amount of work using two tractors would take exactly the same amount of time as one farmer working one portion of work, but in real computers the machine has other work to do even if it seems idle.在一个理想的世界中,两个农民使用两台拖拉机工作两倍的工作量与一个农民工作一部分工作所花费的时间完全相同,但在真实的计算机中,即使机器看起来空闲,机器也有其他工作要做。 There are task switching, the OS kernel has to run and monitor hardware devices, memory caches needs to be flushed and invalidated between CPU cores, your browser needs to run, the village elder is running a meeting to discuss who should get the tractors and when, etc.有任务切换,操作系统 kernel 必须运行和监控硬件设备,memory 缓存需要在 CPU 内核之间刷新和失效,你的浏览器需要运行,村长正在开会讨论谁应该得到拖拉机以及什么时候, ETC。

As the number of workers increases beyond the number of tractors, farmers don't just hog the tractors for themselves.随着工人数量的增加超过拖拉机的数量,农民不只是为自己独占拖拉机。 Instead they made an arrangement that they'd pass the tractors around every three hours or so.相反,他们做了一个安排,每三个小时左右就可以通过拖拉机。 This means that the seventh farmer don't have to wait for two days to get their share of tractor time.这意味着第七个农民不必等待两天来获得他们的拖拉机时间。 However, there's a cost to transferring tractors between farmlands, just as there are costs for CPU to switch between processes;但是,在农田之间转移拖拉机是有成本的,就像 CPU 在进程之间切换一样有成本; task switch too frequently and the CPU is not actually doing work, and switch to infrequently and you get resource starvation as some jobs takes too long to start being worked on.任务切换太频繁,CPU 实际上并没有在工作,并且不经常切换,你会遇到资源匮乏,因为某些工作需要很长时间才能开始工作。

A more sensible test would be to keep the size of farmland constant and just increase the number of farmers.一个更明智的测试是保持耕地面积不变,只增加农民的数量。 In your code, that would correspond to this change:在您的代码中,这将对应于此更改:

def rand_val(num_workers):
    num = []
    for i in range(200000000 / num_workers):
        num = random.random()
    print('done')

def main():
    for iii in range(15):
        processes = [Process(target=lambda: rand_val(iii)) for _ in range(iii)]
        ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM