首页 > 解决方案 > 使用多进程时python中内存映射时序的解释

问题描述

我正在使用 36 核 HPC 节点。规范是该节点有 2 个 Intel Xeon E5-2695 v4 CPU,每个 CPU 有 18 个内核。我正在尝试从主进程写入内存映射,子进程读取内存映射并更新它。子进程在更新前会休眠一段时间。我并行启动多个子进程。

我正在做一些性能测试,遇到了一个我在代码结果下面解释过的场景。

import time
from mmap import mmap
from multiprocessing import Process, Lock

f = open("results.csv", "w")
f.write("mmap_time,total_time\n")

def sub_process(m, mutex):
        while True:
                mutex.acquire()
                if m[0] == 72:                                  # equivalent to H
                        time.sleep(0.001)                       # sleep for 1 millisecond
                        m.seek(0)
                        m.write(bytes("child", "utf-8"))
                mutex.release()
                time.sleep(0.00001)

n = 80                                                          #Num of Subprocess

m = []
mutex = []
process = []
for i in range(n):
        m.append(mmap(-1, 5))
        mutex.append(Lock())
        process.append(Process(target = sub_process, args = (m[i], mutex[i])))
        process[i].start()

for it in range(100):
        total_start_time = time.time_ns() / (10 ** 6)           # milliseconds time
        mmap_dict = {}
        for i in range(n):
                mmap_dict[m[i]] = mutex[i]
        for mmap,mu in mmap_dict.items():
                mu.acquire()
                mmap.seek(0)
                mmap.write(bytes("Hello", "utf-8"))
                mu.release()
        condition = True
        mmap_start_time = time.time_ns() / (10 ** 6)
        while condition:
                l = []                                          # list to hold the mmap that were updated
                for mmap,mu in mmap_dict.items():
                        mu.acquire()
                        mmap.seek(0)
                        if mmap[0] == 99:                       # equivalent to c
                                l.append(mmap)
                        mu.release()
                for mmap in l:del mmap_dict[mmap]
                if len(mmap_dict) == 0:
                        del mmap_dict
                        condition = False
        mmap_end_time = time.time_ns() / (10 ** 6)
        total_end_time = time.time_ns() / (10 ** 6)
        f.write(str(mmap_end_time - mmap_start_time) + "," + str(total_end_time - total_start_time) + "\n")
f.close()
for i in range(n):
        process[i].terminate()
        m[i].close()

在每个子进程中,当它检测到它的内存映射被更新时。子进程休眠 1 毫秒,然后更新内存映射。

输出如下(所有时间都是100次迭代的平均时间,以毫秒为单位)

|---------------------|-----------------|-----------------|
|    Num_Subprocess   |    mmap_time    |    total_time   |
|---------------------|-----------------|-----------------|
|          1          |   1.122416992   |    1.126069336  |
|---------------------|-----------------|-----------------|
|         10          |   1.115305176   |    1.130327148  |
|---------------------|-----------------|-----------------|
|         40          |   1.133754883   |    1.212219238  |
|---------------------|-----------------|-----------------|
|         80          |   1.172145996   |    1.350251465  |
|---------------------|-----------------|-----------------|

我知道 mmap 时间在 1.1 范围内,因为我只记录主进程看到反射所用的时间。但是,对于 40 个子进程,我预计总时间至少为 2 毫秒,因为我在子进程中睡眠 1 毫秒,而我只有 36 个内核,而对于 80 个子进程,我预计至少 3 毫秒。有人可以解释为什么总时间低于预期值吗?我的代码中有错误吗?

标签: pythonparallel-processingcpu-architecturetimingmemory-mapping

解决方案


我认为这里发生的事情是,当子进程开始睡眠时,它不会占用资源。相反,另一个子进程开始在核心上运行。我怀疑这就是原因,总时间低于预期值。

我尝试在子工作人员中添加一些大约需要 1 毫秒的随机计算,而不是睡眠。我在我的机器上标记了计算。

def sub_process(m, mutex):
        while True:
                mutex.acquire()
                if m[0] == 72:
                        for i in range(1000):
                                result = math.pow(math.sqrt(math.cos(math.sin(i*math.pi))),2)
                        m.seek(0)
                        m.write(bytes("child", "utf-8"))
                mutex.release()
                time.sleep(0.00001)

现在我的结果是

|---------------------|-----------------|-----------------|
|    Num_Subprocess   |    mmap_time    |    total_time   |
|---------------------|-----------------|-----------------|
|          1          |     1.00910     |     1.01289     |
|---------------------|-----------------|-----------------|
|         10          |     6.29030     |     6.30628     |
|---------------------|-----------------|-----------------|
|         40          |     19.72357    |     19.78807    |
|---------------------|-----------------|-----------------|
|         80          |     51.22329    |     51.33896    |
|---------------------|-----------------|-----------------|

尽管如此,现在似乎时机已经成熟。结果更加现实和可接受。


推荐阅读