随着时间的推移,我们的dask调度程序进程似乎在内存中膨胀并且执行继续。目前我们看到它使用5GB的mem,这似乎很高,因为据说所有数据都存在于工作节点上:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
31172 atoz 20 0 5486944 5.071g 7100 S 23.8 65.0 92:38.64 dask-scheduler
启动调度程序时,我们的内存使用量将低于1GB。重新启动网络做一个client.restart()似乎没什么帮助,只有杀掉调度程序进程本身并重新启动才能释放内存。
每个执行任务的内存使用量是多少? 调度程序真的只维护指向哪个worker包含未来结果的指针吗?
---- ----编辑
我认为我的主要关注点是为什么client.restart()似乎没有释放调度程序进程使用的内存。我显然不希望它释放所有内存,而是回到基准级别。我们使用client.map在不同输入的列表中执行我们的功能。在执行之后,一遍又一遍地重新启动客户端并拍摄我们的调度程序内存的快照,我们看到以下增长:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27955 atoz 20 0 670556 507212 13536 R 43.7 6.2 1:23.61 dask-scheduler
27955 atoz 20 0 827308 663772 13536 S 1.7 8.1 16:25.85 dask-scheduler
27955 atoz 20 0 859652 696408 13536 S 4.0 8.5 19:18.04 dask-scheduler
27955 atoz 20 0 1087160 923912 13536 R 62.3 11.3 20:03.15 dask-scheduler
27955 atoz 20 0 1038904 875788 13536 S 3.7 10.7 23:57.07 dask-scheduler
27955 atoz 20 0 1441060 1.163g 12976 S 4.3 14.9 35:54.45 dask-scheduler
27955 atoz 20 0 1646204 1.358g 12976 S 4.3 17.4 37:05.86 dask-scheduler
27955 atoz 20 0 1597652 1.312g 12976 S 4.7 16.8 37:40.13 dask-scheduler
我想我在做一个client.restart()后感到很惊讶,我们没有看到内存使用量回到某个基线。
----进一步编辑---- 关于我们正在运行的更多信息,因为建议是我们是否传递大型数据结构,直接将它们发送给工作人员。
我们发送一个字典作为每个任务的输入,当json转储dict时,大多数都不到1000个字符。
----甚至进一步编辑:转载问题---- 我们今天再次复制了这个问题。我杀掉了调度程序并重新启动它,我们有大约5.4 GB的可用内存,然后我们运行了我将在69614字典对象下面粘贴的函数,这些对象确实包含一些基于文件的信息(我们所有的工作程序都映射到同一个NFS数据存储区,我们使用Dask作为分布式文件分析系统。
这是函数(注意:squarewheels4是一个自行开发的惰性文件提取和分析包,它使用Acora和libarchive作为其基础,用于从压缩存档中获取文件并索引文件。)
def get_mrc_failures(file_dict):
from squarewheels4.platforms.ucs.b_series import ChassisTechSupport
from squarewheels4.files.ucs.managed.chassis import CIMCTechSupportFile
import re
dimm_info_re = re.compile(r"(?P<slot>[^\|]+)\|(?P<size>\d+)\|.*\|(?P<pid>\S+)")
return_dict = file_dict
return_dict["return_code"] = "NOT_FILLED_OUT"
filename = "{file_path}{file_sha1}/{file_name}".format(**file_dict)
try:
sw = ChassisTechSupport(filename)
except Exception as e:
return_dict["return_code"] = "SW_LOAD_ERROR"
return_dict["error_msg"] = str(e)
return return_dict
server_dict = {}
cimcs = sw.getlist("CIMC*.tar.gz")
if not cimcs:
return_dict["return_code"] = "NO_CIMCS"
return_dict["keys_list"] = str(sw.getlist("*"))
return return_dict
for cimc in cimcs:
if not isinstance(cimc, CIMCTechSupportFile): continue
cimc_id = cimc.number
server_dict[cimc_id] = {}
# Get MRC file
try:
mrc = cimc["*MrcOut.txt"]
except KeyError:
server_dict[cimc_id]["response_code"] = "NO_MRC"
continue
# see if our end of file marker is there, should look like:
# --- END OF FILE (Done!
whole_mrc = mrc.read().splitlines()
last_10 = whole_mrc[-10:]
eof_line = [l for l in last_10 if b"END OF FILE" in l]
server_dict[cimc_id]["response_code"] = "EOF_FOUND" if eof_line else "EOF_MISSING"
if eof_line:
continue
# get DIMM types
hit_inventory_line = False
dimm_info = []
dimm_error_lines = []
equals_count = 0
for line in whole_mrc:
# regex each line... sigh
if b"DIMM Inventory" in line:
hit_inventory_line = True
if not hit_inventory_line:
continue
if hit_inventory_line and b"=========" in line:
equals_count += 1
if equals_count > 2:
break
continue
if equals_count < 2:
continue
# we're in the dimm section and not out of it yet
line = str(line)
reg = dimm_info_re.match(line)
if not reg:
#bad :/
dimm_error_lines.append(line)
continue
dimm_info.append(reg.groupdict())
server_dict[cimc_id]["dimm_info"] = dimm_info
server_dict[cimc_id]["dimm_error_lines"] = dimm_error_lines
return_dict["return_code"] = "COMPLETED"
return_dict["server_dict"] = server_dict
return return_dict
```
期货的生成如下:
futures = client.map(function_name, file_list)
在这种状态之后,我的目标是尝试恢复并让dask释放它已分配的内存,这是我的努力: 在取消期货之前:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21914 atoz 20 0 6257840 4.883g 2324 S 0.0 62.6 121:21.93 dask-scheduler
atoz@atoz-sched:~$ free -h
total used free shared buff/cache available
Mem: 7.8G 7.1G 248M 9.9M 415M 383M
Swap: 8.0G 4.3G 3.7G
取消期货时:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21914 atoz 20 0 6258864 5.261g 5144 R 60.0 67.5 122:16.38 dask-scheduler
atoz@atoz-sched:~$ free -h
total used free shared buff/cache available
Mem: 7.8G 7.5G 176M 9.4M 126M 83M
Swap: 8.0G 4.1G 3.9G
取消期货后:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21914 atoz 20 0 6243760 5.217g 4920 S 0.0 66.9 123:13.80 dask-scheduler
atoz@atoz-sched:~$ free -h
total used free shared buff/cache available
Mem: 7.8G 7.5G 186M 9.4M 132M 96M
Swap: 8.0G 4.1G 3.9G
执行client.restart()
之后 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21914 atoz 20 0 6177424 5.228g 4912 S 2.7 67.1 123:20.04 dask-scheduler
atoz@atoz-sched:~$ free -h
total used free shared buff/cache available
Mem: 7.8G 7.5G 196M 9.4M 136M 107M
Swap: 8.0G 4.0G 4.0G
无论我通过分布式系统运行什么,我的期望是在取消期货之后它会回到至少接近正常......并且在做了client.restart()之后我们肯定会接近我们的正常基线。我错了吗?
---第二次复制---- 使用以下步骤重现行为(尽管不是总内存耗尽):
这是我的工作人员职能
def get_fault_list_v2(file_dict):
import libarchive
return_dict = file_dict
filename = "{file_path}{file_sha1}/{file_name}".format(**file_dict)
with libarchive.file_reader(filename) as arc:
for e in arc:
pn = e.pathname
return return_dict
我在68617次迭代/文件中运行了
在跑步之前我们看到了这么多内存被利用: PID用户PR NI VIRT RES SHR S%CPU%MEM TIME + COMMAND 12256 atoz 20 0 1345848 1.107g 7972 S 1.7 14.2 47:15.24 dask-scheduler
atoz@atoz-sched:~$ free -h
total used free shared buff/cache available
Mem: 7.8G 3.1G 162M 22M 4.5G 4.3G
Swap: 8.0G 3.8G 4.2G
跑步后我们看到了这么多:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12256 atoz 20 0 2461004 2.133g 8024 S 1.3 27.4 66:41.46 dask-scheduler
在做了client.restart后,我们看到了:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12256 atoz 20 0 2462756 2.134g 8144 S 6.6 27.4 66:42.61 dask-scheduler
答案 0 :(得分:2)
通常,任务在调度程序上应占用不到一千字节。有一些事情你可以绊倒,导致存储更多,其中最常见的是包括任务图中的数据,如下所示。
直接包含在任务图中的数据存储在调度程序中。这种情况通常发生在直接在诸如submit:
之类的调用中使用大数据时x = np.random.random(1000000) # some large array
future = client.submit(np.add, 1, x) # x gets sent along with the task
x = np.random.random(1000000) # some large array
x = client.scatter(x) # scatter data explicitly to worker, get future back
future = client.submit(np.add, 1, x) # only send along the future
同样的原则也存在使用其他API。有关详细信息,建议您提供mcve。否则很难提供帮助。