multiprocessing.Array 内存分配

multiprocessing.Array allocation in memory

我正在创建一个 multiprocessing.Array 并使用 htop 检查它在内存中的大小。 另外,我正在查看访问数组的最后一个元素需要多少时间。

import multiprocessing as mp
import numpy as np
import time
X = 1 # 1 GB
mp_array = mp.Array('B', X*1024*1024*1024, lock = True)
np_array = np.frombuffer(mp_array.get_obj(), dtype = 'B')

t1 = time.time()
for i1 in range(10**7):
    a = np_array[-1]
print(time.time() - t1)

当我创建一个 'small' 数组时,我在 htop 中看到内存如何增加 GB,如果大小为 3 或 6 GB,则相同,所以所有数组都进入正在使用的内存(绿色的)。 我的电脑上有 32 GB,所以我尝试创建一个 20GB 的数组,但是当我这样做时,我看到绿色内存与创建数组之前的值相同,并且所有内存都转到黄色内存(缓存,对于我读过的内容)。 我什至尝试创建一个比我的总 RAM 还大的数组,并且成功了。所以我真的不知道后台发生了什么(没有使用交换)。 各场景时间基本一致,循环1.5s左右

现在,这只是测试,对于我正在处理的程序,我在一台 8 GB 的机器上创建了六个独立的共享内存阵列,每个 X GB。 (仅供参考:每个数组都是相机流的缓冲区)

我试过 X = 0.5,所以总共应该使用 3 GB,它按预期工作,但是当我使用 X = 1 时,其中的一小部分进入缓存。我猜前几个数组分配在 'active' 内存中,其余的分配到缓存中?在我的粗略测试中,我发现访问任何类型的内存时都没有时间差异。但我真的不明白这里发生了什么,也不明白为什么我可以创建一个比我的总 RAM 更大的数组。

你有什么见解可以给我吗?

sharedctypes 从称为“Arena”的块中分配内存,这些块是内存映射文件。尽最大努力从非存储支持目录创建所述文件(你的 fs 的一部分只在 ram 中......)以获得最佳性能。但是,在创建文件之前会检查可用的 space,因此如果内存中的临时文件夹中没有 space,则可以在磁盘上的其他地方创建临时文件。然后最终将缓冲区作为 mmap 的内存视图:

multiprocessing/heap.py

else: #if sys.platform != 'win32':

    class Arena(object):
        """
        A shared memory area backed by a temporary file (POSIX).
        """

        if sys.platform == 'linux':
            _dir_candidates = ['/dev/shm']
        else:
            _dir_candidates = []

        def __init__(self, size, fd=-1):
            self.size = size
            self.fd = fd
            if fd == -1:
                # Arena is created anew (if fd != -1, it means we're coming
                # from rebuild_arena() below)
                self.fd, name = tempfile.mkstemp(
                     prefix='pym-%d-'%os.getpid(),
                     dir=self._choose_dir(size))
                os.unlink(name)
                util.Finalize(self, os.close, (self.fd,))
                os.ftruncate(self.fd, size)
            self.buffer = mmap.mmap(self.fd, self.size)

        def _choose_dir(self, size):
            # Choose a non-storage backed directory if possible,
            # to improve performance
            for d in self._dir_candidates:
                st = os.statvfs(d)
                if st.f_bavail * st.f_frsize >= size:  # enough free space?
                    return d
            return util.get_temp_dir()