- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
multiprocessing.Pool
它在 1 个或多个子进程中调用一个函数来生成大量数据。 multiprocessing.shared_memory.SharedMemory
对象并使用由 shared_memory
分配的默认名称. SharedMemory
的字符串名称反对主进程。 SharedMemory
对象被链接、消费,然后 取消链接和关闭 . resource_tracker
的警告:
/usr/local/lib/python3.8/multiprocessing/resource_tracker.py:216: UserWarning: resource_tracker: There appear to be 10 leaked shared_memory objects to clean up at shutdown
warnings.warn('resource_tracker: There appear to be %d '
/usr/local/lib/python3.8/multiprocessing/resource_tracker.py:229: UserWarning: resource_tracker: '/psm_e27e5f9e': [Errno 2] No such file or directory: '/psm_e27e5f9e'
warnings.warn('resource_tracker: %r: %s' % (name, e))
/usr/local/lib/python3.8/multiprocessing/resource_tracker.py:229: UserWarning: resource_tracker: '/psm_2cf099ac': [Errno 2] No such file or directory: '/psm_2cf099ac'
<8 more similar messages omitted>
由于我在主进程中取消了共享内存对象的链接,因此我对这里发生的事情感到困惑。我怀疑这些消息发生在子进程中(在本例中,我使用大小为 1 的进程池进行了测试)。
import multiprocessing
import multiprocessing.shared_memory as shared_memory
def create_shm():
shm = shared_memory.SharedMemory(create=True, size=30000000)
shm.close()
return shm.name
def main():
pool = multiprocessing.Pool(processes=4)
tasks = [pool.apply_async(create_shm) for _ in range(200)]
for task in tasks:
name = task.get()
print('Getting {}'.format(name))
shm = shared_memory.SharedMemory(name=name, create=False)
shm.close()
shm.unlink()
pool.terminate()
pool.join()
if __name__ == '__main__':
main()
我发现在我自己的笔记本电脑(Linux Mint 19.3)上运行该示例运行良好,但是在两台不同的服务器机器(未知的操作系统配置,但两者不同)上运行它确实会出现问题。在所有情况下,我都从 docker 容器运行代码,因此 Python/软件配置是相同的,唯一的区别是 Linux 内核/主机操作系统。
resource_tracker
(我认为这是一个单独的进程)在主进程退出之前没有收到更新。我不明白
resource_tracker
的作用足以完全理解我刚刚提出的建议。
最佳答案
理论上和基于 SharedMemory
的当前实现,应该会出现警告。主要原因是您创建的每个共享内存对象都被跟踪两次:第一,当它由 Pool
中的一个进程生成时。目的;其次,当它被主进程消耗时。这主要是因为 SharedMemory
的构造函数的当前实现将 register
共享内存对象不管是否create
参数设置为 True
或者它的值为 False
.
因此,当您拨打 shm.unlink()
时在主进程中,您正在做的是在其生产者( Pool
中的某个进程)开始清理它之前完全删除共享内存对象。结果,当池被销毁时,它的每个成员(如果他们有任务)都必须自行清理。第一个关于泄漏资源的警告可能是指Pool
中进程实际创建的共享内存对象。从未得到过 unlinked
通过相同的过程 .而且,No such file or directory
警告是由于主进程有 unlinked
Pool
中的进程之前与共享内存对象关联的文件被摧毁。
the linked bug report中提供的解决方案可能会阻止消费进程产生额外的资源跟踪器,但它并不能完全防止当消费进程决定删除它没有创建的共享内存对象时出现的问题。这是因为产生共享内存对象的进程仍然需要做一些清理,即一些 unlinking
, 在它退出或被销毁之前。
您没有看到这些警告这一事实令人费解。但这很可能与操作系统调度、子进程中未刷新的缓冲区以及创建进程池时使用的 start 方法的组合有关。
为了比较,当我使用 fork
作为我机器上的启动方法,我收到警告。否则,当 spawn
时我看不到警告和 forkserver
被使用。我在您的代码中添加了参数解析,以便于测试不同的启动方法:
#!/usr/bin/env python3
# shm_test_script.py
"""
Use --start_method or -s to pick a process start method when creating a process Pool.
Use --tasks or -t to control how many shared memory objects should be created.
Use --pool_size or -p to control the number of child processes in the create pool.
"""
import argparse
import multiprocessing
import multiprocessing.shared_memory as shared_memory
def create_shm():
shm = shared_memory.SharedMemory(create=True, size=30000000)
shm.close()
return shm.name
def main(tasks, start_method, pool_size):
multiprocessing.set_start_method(start_method, force=True)
pool = multiprocessing.Pool(processes=pool_size)
tasks = [pool.apply_async(create_shm) for _ in range(tasks)]
for task in tasks:
name = task.get()
print('Getting {}'.format(name))
shm = shared_memory.SharedMemory(name=name, create=False)
shm.close()
shm.unlink()
pool.terminate()
pool.join()
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
'--start_method', '-s',
help='The multiproccessing start method to use. Default: %(default)s',
default=multiprocessing.get_start_method(),
choices=multiprocessing.get_all_start_methods()
)
parser.add_argument(
'--pool_size', '-p',
help='The number of processes in the pool. Default: %(default)s',
type=int,
default=multiprocessing.cpu_count()
)
parser.add_argument(
'--tasks', '-t',
help='Number of shared memory objects to create. Default: %(default)s',
default=200,
type=int
)
args = parser.parse_args()
main(args.tasks, args.start_method, args.pool_size)
鉴于
fork
是最终显示警告的唯一方法(至少对我而言),也许以下关于它的声明实际上有一些内容:
The parent process uses os.fork() to fork the Python interpreter. Thechild process, when it begins, is effectively identical to the parentprocess. All resources of the parent are inherited by the childprocess. Note that safely forking a multithreaded process isproblematic.
warnings.warn
行添加
os.getpid()
到打印的字符串。例如,使用
"resource_tracker:"
更改任何警告至
"resource_tracker %d: " % (os.getpid())
应该足够了。如果你这样做了,你会注意到警告来自各种进程,这些进程既不是子进程,也不是主进程本身。
Pool
一样多。大小,并且它们的进程ID与主进程或子进程不同:
chmod +x shm_test_script.py
./shm_test_script.py -p 10 -t 50 -s fork > log 2> err
awk -F ':' 'length($4) > 1 { print $4 }' err | sort | uniq -c
这应该显示十行,每行都预先加上来自相应资源跟踪器的投诉数量。每行还应该包含一个 PID,该 PID 应该不同于主进程和子进程。
关于Python 3.8 shared_memory resource_tracker 在应用程序关闭时产生意外警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62748654/
我正在学习 Python 中的共享内存,尤其是 python 3.8 模块 multiprocessing.shared_memory .我没有看到文档中提到锁定。 (虽然父模块 multiproce
我正在使用 multiprocessing.Pool它在 1 个或多个子进程中调用一个函数来生成大量数据。 工作进程创建一个 multiprocessing.shared_memory.SharedM
我正在尝试理解 shared_memory 的一些操作。 查看 source ,看起来该模块在 UNIX 环境中使用 shm_open(),在 Windows 上使用 CreateFileMappin
我正在使用 Python 3.8 的新 shared_memory 模块,但无法在未终止使用它的进程的情况下释放共享内存。 创建和使用共享内存块shm后,我在所有进程中通过shm.close()关闭它
我正在使用 boost shared_memory_manager 模板在共享内存中创建 vector : using namespace boost::interprocess; typedef a
我为我的应用程序创建了一个 1MB 的共享内存空间。 每个用户都是一个,只有一个包含一些信息的数组,可以从大约 10 个并发进程访问,并且在它的监视器上,用户可以看到每个进程的进度。 Evey 进程从
我是一名优秀的程序员,十分优秀!