如何获取python的多处理数组'指针并将其传递给Cpp程序?
Posted
技术标签:
【中文标题】如何获取python的多处理数组\'指针并将其传递给Cpp程序?【英文标题】:How to get python's multiprocessing array'pointer and pass it to Cpp program?如何获取python的多处理数组'指针并将其传递给Cpp程序? 【发布时间】:2020-06-22 10:19:41 【问题描述】:我现在需要在 python 中请求数组,并将它们传递给 Cpp 程序,但 python 仍然需要处理它们。但是我发现当我使用多处理时,数组的地址会改变。
以下是我的代码:
//在test.h中导出dll,这个是test.cpp #include “test.h” #include使用命名空间标准; 无效的一些工作(双*数据,长*标志) cout # test.py import multiprocessing as mp from multiprocessing.sharedctypes import RawArray import ctypes data = RawArray(ctypes.c_double, 2000) flag = RawArray(ctypes.c_long, 20) pkg = ctypes.cdll.LoadLibrary(r"test.dll") pkg.someWork.argtypes = [ ctypes.POINTER(ctypes.c_double * 2000),# dataArray ctypes.POINTER(ctypes.c_long * 20)#flagArray ] def proc_py(): idx = 0 while True: if flag[idx] == 1: # do something flag[idx] = 0 idx = (idx + 1) % 20 def proc_cpp(): pkg.someWork(ctypes.pointer(data), ctypes.pointer(flag)) def main(): p_cpp = mp.Process(target=proc_cpp, args=()) p_py = mp.Process(target=proc_py, args=()) p_cpp .start() p_py .start() p_cpp .join() p_py .join() if __name__ == '__main__': print("py flag address:", ctypes.byref(flag)) # proc_cpp() main()
结果是:我刚刚在python中运行
proc_cpp
,地址是一样的:py flag address: <cparam 'P' (0000019DA8282400)> cpp flag address: 0000019DA8282400
但是当我运行
main
时,地址不同:py flag address: <cparam 'P' (000001CB42A32400)> cpp flag address: 0000012F1E152400
我知道python的多处理必须使用共享内存在处理之间共享内存,但是我使用
mp.Array
/Array.get_obj()
和mp.sharedctypes.RawArray
/ctypes.pointer()
都失败了。有什么办法可以解决我的问题吗?
【问题讨论】:
共享内存不一定映射到不同进程中的相同虚拟地址。不要期望地址匹配。 @MarkTolonen 谢谢你的回复,但似乎如果我想将数组传递给 c/cpp 程序,我必须传递指针。有什么建议可以满足 c/cpp 和 python 可以在多处理任务中使用共享数组的要求吗? 【参考方案1】:不要在“运行一次”主代码之外创建RawArray
,否则您正在制作不同 数组。在主进程中创建一次RawArray
,并将RawArray
作为参数传递给新进程的目标函数。每个进程“看到”的虚拟地址是不同的,但物理内存是一样的。
这是一个例子:
test.cpp:
这将显示指针地址,然后更改共享数组中的指定索引。
#include <iostream>
#include <cstdint>
using namespace std;
#define API __declspec(dllexport)
extern "C" API
void set(double* data, int index, double value)
cout << data << ' ' << index << ' ' << value << endl;
data[index] = value;
test.py:
这会将共享数组传递给每个进程。主进程也会改变一个元素。使用锁是因为 RawArray 不同步,否则 C++ 代码中的打印会混乱,所以这段代码不会真正并行运行,但它确实说明了进程获得不同的虚拟地址但共享相同的数据。
import multiprocessing as mp
from multiprocessing.sharedctypes import RawArray
from ctypes import *
dll = CDLL('./test')
dll.set.argtypes = POINTER(c_double),c_int,c_double
dll.set.restype = None
def call(lock,data,index,value):
with lock:
dll.set(data,index,value)
if __name__ == '__main__':
# This code runs once in the main process.
# The lock and shared data are created once only and passed to other processes.
lock = mp.Lock()
data = RawArray(c_double, 3)
data[0] = 0.5
p1 = mp.Process(target=call, args=(lock,data,1,1.25))
p2 = mp.Process(target=call, args=(lock,data,2,2.5))
p1.start()
p2.start()
p1.join()
p2.join()
print(list(data))
输出(不同的地址,相同的共享数据):
00000269D66E0000 1 1.25
00000187F0B90000 2 2.5
[0.5, 1.25, 2.5]
【讨论】:
我以为调用cpp程序时py必须通过ctypes.byref
或ctypes.pointer
传递arryay,但不知道它可以直接传递python数组。这个答案很有用,谢谢!
@ChuangMen 它模仿 C 将数组衰减传递给指针。 ctypes
从 .argtypes
定义中知道正确的类型。以上是关于如何获取python的多处理数组'指针并将其传递给Cpp程序?的主要内容,如果未能解决你的问题,请参考以下文章