python - 使用多进程时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 毫秒。有人可以解释为什么总时间低于预期值吗?我的代码中有错误吗?
解决方案
我认为这里发生的事情是,当子进程开始睡眠时,它不会占用资源。相反,另一个子进程开始在核心上运行。我怀疑这就是原因,总时间低于预期值。
我尝试在子工作人员中添加一些大约需要 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 |
|---------------------|-----------------|-----------------|
尽管如此,现在似乎时机已经成熟。结果更加现实和可接受。
推荐阅读
- java - BillingClient:getSkuDetails() 失败。响应码:6
- ios - 如何在 fetch PHAssetCollection 语句中获取“相机胶卷”、“视频”、“收藏夹”、“自拍”和“屏幕截图” - swift 4
- sql - 如何在字符串中执行 SQL 搜索字符串
- sql-server - 如何使用 observables 在电子 ipcMain 和角度 ipcRenderer 之间异步发送数据
- typescript - 获取 TypeScript 字符串枚举的字符串
- html - Wordpress - Navigation Sub Menu
- python - Assignment in `for` loop requires explicit indexing?
- api - Azure Application Gateway with API as a backend pool is not working
- angular - 隐藏 ngx Advance 饼图图例
- cairo - 开罗 - 重叠线 - 没有平局的“死区”