【问题标题】:Place data at pagelocked address without copying将数据放在页面锁定地址而不复制
【发布时间】:2019-08-22 12:34:01
【问题描述】:

我正在 NVIDIA Jetson Nano 上开发一个程序,该程序使用 opencv 从网络摄像头/视频中捕获帧。之后,它在 gpu 上对帧进行一些计算。这是为每一帧完成的。为了减少运行时间,我使用映射内存来避免主机和设备之间的显式复制。问题是我仍然必须将帧复制到共享指针地址,即 HOST 到 HOST 复制,这需要大量时间。我怎样才能减少/减少这个时间,或者如果重新表述,我怎样才能每次有效地更新共享内存位置的帧数据?

目前,我使用np.copyto将框架复制到共享地址

frame = cap.read()
sharedadd = cuda.pagelocked_empty((1,3,500,500), dtype=np.float32),mem_flags=cuda.host_alloc_flags.DEVICEMAP) # allocate     mapped memory
np.copyto(sharedadd, frame.ravel()) # takes quite some time

我尝试使用ctype 指针取消引用共享内存位置并为其分配新值。但是,它也希望帧是一个 ctype 指针。

frame = cap.read()
sharedadd = cuda.pagelocked_empty((1,3,500,500),dtype=np.float32),mem_flags=cuda.host_alloc_flags.DEVICEMAP) # allocate mapped memory
c_float_p = ctypes.POINTER(ctypes.c_float)
sharedptr = sharedadd.ctypes.data_as(c_float_p)
ctypes.cast(ctypes.addressof(sharedptr), ?).contents # second argument is expected to be a ctype pointer to frame

【问题讨论】:

    标签: numpy optimization ctypes pycuda


    【解决方案1】:

    如何每次有效地更新共享内存位置的帧数据?

    如果我理解正确,您想访问(并更改)shared_ptr 指向的浮点数组的内容。

    给定:

    frame = cap.read()
    sharedadd = cuda.pagelocked_empty((1,3,500,500),dtype=np.float32),mem_flags=cuda.host_alloc_flags.DEVICEMAP) # allocate mapped memory
    c_float_p = ctypes.POINTER(ctypes.c_float)
    sharedptr = sharedadd.ctypes.data_as(c_float_p)
    

    您可以通过索引shared_ptr直接访问内容:

    float_1 = shared_ptr[0]  # read
    shared_ptr[0] = float_1 + 100.0  # write
    

    这是一个简单的纯 python(无 cuda)示例:

    >>> import ctypes
    >>> floats = [100.0, 200.0, 300.0]  # array of python floats
    >>> c_floats = (ctypes.c_float * len(floats))(*floats)  # array of ctypes floats
    >>> p_floats =  ctypes.cast(c_floats, ctypes.POINTER(ctypes.c_float))  # pointer to array of ctypes floats
    >>> p_floats[0]  # read
    100.0
    >>> p_floats[1]  # read
    200.0
    >>> p_floats[2]  # read
    300.0
    >>> p_floats[2] = 400.0  # write index 2 (was 300.0)
    >>> p_floats[2]  # read newly written index
    400.0
    >>> c_floats[2]  # check index 2 has been updated on the array itself
    400.0
    

    [编辑]

    我可以通过一次写入所有索引来做到这一点吗?

    您不能从 ctypes 指针切片,但可以使用 ctypes.memmove()

    按照前面的例子:

    >>> new_floats = [1000.0, 2000.0, 3000.0]
    >>> c_new_floats = (ctypes.c_float * len(new_floats))(*new_floats)
    >>> p_new_floats = ctypes.cast(c_new_floats, ctypes.POINTER(ctypes.c_float))
    >>> ctypes.memmove(p_floats, p_new_floats, len(new_floats) * ctypes.sizeof(ctypes.c_float))  # copy new floats to previous array through pointers.
    >>> p_floats[0]
    1000.0
    >>> p_floats[1]
    2000.0
    >>> p_floats[2]
    3000.0
    

    【讨论】:

    • 我可以一次写入所有索引吗?
    • ctypes.memmove()所用时间与np.copyto()相似
    猜你喜欢
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    • 2011-09-22
    • 1970-01-01
    • 1970-01-01
    • 2016-07-04
    • 1970-01-01
    相关资源
    最近更新 更多