簡體   English   中英

使用 Python 共享內存的分段錯誤

[英]Segmentation Fault using Python Shared Memory

函數store_in_shm將一個 numpy 數組寫入共享內存,而第二個函數read_from_shm使用同一共享內存空間中的數據創建一個 numpy 數組並返回 numpy 數組。

但是,在 Python 3.8 中運行代碼會出現以下分段錯誤:

zsh:分段錯誤 python foo.py

為什么從函數read_from_shm內部訪問 numpy 數組沒有問題,但是在函數外再次訪問 numpy 數組時出現分段錯誤?

輸出:

From read_from_shm(): [0 1 2 3 4 5 6 7 8 9]
zsh: segmentation fault  python foo.py
% /Users/athena/opt/anaconda3/envs/test/lib/python3.8/multiprocessing/resource_tracker.py:203: UserWarning: resource_tracker: There appear to be 1 leaked shared_memory objects to clean up at shutdown
  warnings.warn('resource_tracker: There appear to be %d '

文件

import numpy as np
from multiprocessing import shared_memory

def store_in_shm(data):
    shm = shared_memory.SharedMemory(name='foo', create=True, size=data.nbytes)
    shmData = np.ndarray(data.shape, dtype=data.dtype, buffer=shm.buf)
    shmData[:] = data[:]
    shm.close()
    return shm

def read_from_shm(shape, dtype):
    shm = shared_memory.SharedMemory(name='foo', create=False)
    shmData = np.ndarray(shape, dtype, buffer=shm.buf)
    print('From read_from_shm():', shmData)
    return shmData

if __name__ == '__main__':
    data = np.arange(10)
    shm = store_in_shm(data)
    shmData = read_from_shm(data.shape, data.dtype)
    print('From __main__:', shmData)    # no seg fault if we comment this line
    shm.unlink()

基本上問題似乎是當函數返回時shm被垃圾收集時,底層的 mmap'ed 文件(由shmread_from_shm擁有)正在關閉。 然后shmData指回它,這是您獲得段錯誤的地方(用於指代關閉的 mmap)這似乎是一個已知錯誤,但可以通過保留對shm的引用來解決。

此外,所有SharedMemory實例都希望close() 'd,其中一個在不再需要時被unlink() 'ed。 如果你自己不調用shm.close() ,它會在前面提到的 GC 中調用,在 Windows 上,如果它是當前“打開”的唯一一個,則共享內存文件將被刪除。 當您在store_in_shm調用shm.close() ,您會引入操作系統依賴項,因為在 Windows 上數據將被刪除,而 MacOS 和 Linux 將保留直到調用unlink

最后,盡管這不會出現在您的代碼中,但當前存在另一個問題,即從獨立進程(而不是子進程)訪問數據可能會過早地刪除底層 mmap。 SharedMemory是一個非常新的庫,希望所有問題都能很快解決。

您可以重寫給定的示例以保留對“第二個” shm的引用,只需使用其中一個即可unlink

import numpy as np
from multiprocessing import shared_memory

def store_in_shm(data):
    shm = shared_memory.SharedMemory(name='foo', create=True, size=data.nbytes)
    shmData = np.ndarray(data.shape, dtype=data.dtype, buffer=shm.buf)
    shmData[:] = data[:]
    #there must always be at least one `SharedMemory` object open for it to not
    #  be destroyed on Windows, so we won't `shm.close()` inside the function,
    #  but rather after we're done with everything.
    return shm

def read_from_shm(shape, dtype):
    shm = shared_memory.SharedMemory(name='foo', create=False)
    shmData = np.ndarray(shape, dtype, buffer=shm.buf)
    print('From read_from_shm():', shmData)
    return shm, shmData #we need to keep a reference of shm both so we don't
                        #  segfault on shmData and so we can `close()` it.

if __name__ == '__main__':
    data = np.arange(10)
    shm1 = store_in_shm(data)
    #This is where the *Windows* previously reclaimed the memory resulting in a 
    #  FileNotFoundError because the tempory mmap'ed file had been released.
    shm2, shmData = read_from_shm(data.shape, data.dtype)
    print('From __main__:', shmData)
    shm1.close() 
    shm2.close()
    #on windows "unlink" happens automatically here whether you call `unlink()` or not.
    shm2.unlink() #either shm1 or shm2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM