【问题标题】:How can I access a python shared memory from cython?如何从 cython 访问 python 共享内存?
【发布时间】:2020-08-14 20:39:57
【问题描述】:

我有两个进程,一个创建共享内存,第二个访问它。我正在使用 Python 3.8。

第二个进程可以选择仅使用 python 函数或通过 cython 访问共享内存。 cython 选项失败 - 我得到一个 SIGSEGV。

是否有一些特殊的方法可以在 cython 中获取共享内存? docs 似乎没有显示如何实际获取 python 共享内存。

进程 1 (setup_shm.py):

from multiprocessing import shared_memory
import numpy as np
import argparse
from package.get_shm import main as get_shm
from multiprocessing import Process


def main(cython=None):
    arr_share = np.array([[1.3424, 23.24324], [1.4234, .08682]], dtype='f')
    shape, dtype = arr_share.shape, arr_share.dtype
    # Create a shared memory of size arr_share.nbytes
    shm = shared_memory.SharedMemory(create=True, size=arr_share.nbytes)
    # Create array using the buffer of shm
    shm_np_array = np.ndarray(shape=shape, dtype=dtype, buffer=shm.buf)
    # Copy the data into the shared memory
    np.copyto(shm_np_array, arr_share)
    print('shared name {}'.format(shm.name))
    print('shared size {}'.format(arr_share.nbytes))
    print(arr_share)
    p = Process(target=get_shm, args=(shm.name,), kwargs={'cython': cython})
    p.start()
    p.join()
    shm.close()
    shm.unlink()


def setup():
    parser = argparse.ArgumentParser(description='Shared mem getter')
    parser.add_argument('--cython', action='store_true', help='Use cython to get shared mem')
    args = parser.parse_args()
    main(cython=args.cython)


if __name__ == "__main__":
    setup()

进程 2 (get_shm.py):

from multiprocessing.shared_memory import SharedMemory
import numpy as np
import argparse
import sys
from c_get_shm import Vectors

def main(name, cython=None):
    val = None
    if cython:
        print('getting vector using cython - {}'.format(name))
        vectors = Vectors(name)
        try:
            val = vectors.data.base[0]
        except Exception as e:
            raise (e)
    else:
        shm = SharedMemory(name=name)
        np_array = np.ndarray(shape=(2, 2), dtype='f', buffer=shm.buf)
        print('getting vector using python - {}'.format(name))
        val = np_array[0]
        shm.close()
    print('val is {}'.format(val))
    sys.stdout.flush()
    return


def setup():
    parser = argparse.ArgumentParser(description='Shared mem getter')
    parser.add_argument('name', type=str, help='Shared memory name')
    parser.add_argument('--cython', action='store_true', help='Use cython to get shared mem')
    args = parser.parse_args()
    main(name=args.name, cython=args.cython)


if __name__ == "__main__":
    setup()

Cython 类 (c_get_shm.pyx)

#!python
#cython: language_level=3, boundscheck=False
from multiprocessing import shared_memory
cimport numpy as np
np.import_array()

cdef class Vectors:

    cdef public object shm_name
    cdef public float[:, :] data

    def __init__(self, shm_name):
        print('Vectors Class for getting shared memory - {}'.format(shm_name))
        self.__get_shared_array(shm_name)
        print('data is {}, {}'.format(self.data, self.data.shape))

    def __get_shared_array(self, shm_name: str):
        print('get_shared_array {}'.format(shm_name))
        shm = shared_memory.SharedMemory(name=shm_name)
        print('shm buf is {} size {}'.format(shm.buf, shm.buf.nbytes))
        self.data = np.ndarray(shape=(2, 2), dtype='f', buffer=shm.buf)

Setup.py

from setuptools import setup, Extension
from Cython.Build import cythonize

extensions = [
    Extension("c_get_shm", ["./c_get_shm.pyx"],
              libraries=['rt'])
]
setup(
    ext_modules=cythonize(extensions, gdb_debug=True)
)

我正在运行脚本

  • python ./setup_shm.py --cython
  • python ./setup_shm.py

我设法看到 SIGSEGV 的唯一方法是使用 strace:

Vectors Class for getting shared memory - psm_23cd04df
get_shared_array psm_23cd04df
shm buf is <memory at 0x7f8b4d66df40> size 16
data is <MemoryView of 'ndarray' object>, [2, 2, 0, 0, 0, 0, 0, 0]
[{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV && WCOREDUMP(s)}], 0, NULL) = 868
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_DUMPED, si_pid=868, si_uid=1000, si_status=SIGSEGV, si_utime=0, si_stime=0} ---
close(5)                                = 0
munmap(0x7f8b65698000, 16)              = 0
close(4)                                = 0
unlink("/dev/shm/psm_23cd04df")         = 0

我尝试过 gdb python 并从那里运行脚本,但没有堆栈跟踪。

【问题讨论】:

  • 我认为应该是val = vectors.data[0,0](或至少val = vectors.data.base[0,0])。我怀疑这是否是你的问题。
  • 我唯一能看到的另一件事是你从来没有在 Cython 中close
  • 这些 cmets 实际上非常有用,因为它们会导致更多错误被抛出,而不是代码只是段错误。我认为我有一个可行的解决方案。所以关闭共享内存似乎是正确的答案。
  • 实际上,事实证明我不需要在 cython 类中关闭。主要问题是没有将共享内存声明为 c 变量。

标签: python cython shared-memory python-3.8


【解决方案1】:

对于遇到类似问题的任何人,请确保在 Cython 中声明共享内存。我假设 SIGSEGV 是因为除非你这样做,否则它不允许访问内存。

cdef class Vectors:

    cdef public object shm_name
    cdef public float[:, :] data
    # declare the shared memory in Cython!!
    cdef public object shm

    def __init__(self, shm_name):
        self.__get_shared_array(shm_name)

    def __get_shared_array(self, shm_name: str):
        self.shm = shared_memory.SharedMemory(name=shm_name)
        self.data = np.ndarray(shape=(2, 2), dtype='f', buffer=self.shm.buf)

【讨论】:

    猜你喜欢
    • 2018-05-07
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 2015-09-10
    • 2013-09-30
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    相关资源
    最近更新 更多