提问人:RTC222 提问时间:2/22/2018 最后编辑:wovanoRTC222 更新时间:11/25/2022 访问量:5312
Ctypes:将返回指针转换为数组或 Python 列表的快速方法
Ctypes: fast way to convert a return pointer to an array or Python list
问:
我正在使用ctypes将数组指针传递给dll,并返回指向在dll中使用malloc创建的双精度数组的指针。回到 Python 后,我需要一种快速将指针转换为数组或 Python 列表的方法。
我可以使用这个列表组合,但它很慢,因为有 320,000 个数据点:
list_of_results = [ret_ptr[i] for i in range(320000)]
理想情况下,我会在 Python 中创建数组并将其传递给 dll,但我必须在 dll 中使用 malloc 创建它,因为这是一个动态数组,我事先不知道会有多少数据元素(尽管返回指针也返回数据元素的数量,所以我知道返回 Python 时有多少个)——我使用 realloc 在DLL;我可以将 realloc 与 Python 数组一起使用,但不能保证最后调用 free() 有效。
Here is the relevant Python code:
CallTest = hDLL.Main_Entry_fn
CallTest.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.c_int64]
CallTest.restype = ctypes.POINTER(ctypes.c_double)
ret_ptr = CallTest(DataArray, number_of_data_points)
list_of_results = [ret_ptr[i] for i in range(320000)]
所以我的问题是:将从 dll 返回的指针转换为 Python 列表或数组的最快方法是什么?上面显示的方法太慢了。
答:
9赞
user2357112
2/22/2018
#1
对 ctypes 数组或指针进行切片将自动生成一个列表:
list_of_results = ret_ptr[:320000]
根据“将指针转换为数组”的含义以及可以使用的输出类型,您可以做得更好。例如,您可以直接创建由缓冲区支持的 NumPy 数组,而无需复制数据:
buffer_as_ctypes_array = ctypes.cast(ret_ptr, ctypes.POINTER(ctypes.c_double*320000))[0]
buffer_as_numpy_array = numpy.frombuffer(buffer_as_ctypes_array, numpy.float64)
当然,如果你在仍然需要它的时候释放缓冲区,这将严重破坏。
评论
2赞
RTC222
2/22/2018
明。您的第一个建议 ([:320000]) 就是我所需要的——在我的示例中,它比我使用的列表组合快 35 倍。我想避免为此目的使用 numpy,而您的切片索引正是我所需要的。非常感谢。
0赞
user2357112
2/22/2018
@RTC222:35 倍?这是一个惊喜;在我自己的测试中,我只看到了大约 2.5 倍的加速。我很高兴它似乎为您提供了重大改进,但这种差异很奇怪,可能令人担忧。我想知道这是否是版本差异。(我正在 3.6.3 上测试。
0赞
RTC222
2/22/2018
我正在 3.6.2 上进行测试,这并不能解释差异。这些都是非常小的测量值,所以它们可能会有所不同,但这就是我得到的。任何改进都会有所帮助。
1赞
ShadowRanger
11/18/2022
@RTC222:你可以通过使用 或(复制时速度稍慢,但获得更像本机的访问语义)来获得与代码类似的速度,使用内置模块来制作适当的项目大小,然后使用 的方法直接进行基于内存复制的填充(比切片速度快一个数量级, 并且内存消耗要低得多,尽管访问单个值的成本更高,因为它每次都会构造一个新的 Python)。numpy
memoryview
list
array
array
array.array
frombytes
array.array
int
评论