Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过ctypes提高从Python向C(+;+;)传递数据的速度_C++_Python_Optimization_Ctypes - Fatal编程技术网

C++ 通过ctypes提高从Python向C(+;+;)传递数据的速度

C++ 通过ctypes提高从Python向C(+;+;)传递数据的速度,c++,python,optimization,ctypes,C++,Python,Optimization,Ctypes,我需要为时间关键型机器人应用程序优化循环中的函数调用。我的脚本是在Python中,它通过CyType与我所写的C++库进行接口,然后调用微控制器库。 瓶颈是将位置速度时间点添加到微控制器缓冲区。根据我的时序检查,通过cType调用C++函数大约有代码> 0.45 >代码>秒,在C++侧调用函数使用 0.17 秒。我需要设法减少这种差异 以下是相关的python代码,其中数据是点的2D数组,clibrary通过ctypes加载: data_np = np.vstack([nodes, positi

我需要为时间关键型机器人应用程序优化循环中的函数调用。我的脚本是在Python中,它通过CyType与我所写的C++库进行接口,然后调用微控制器库。 瓶颈是将位置速度时间点添加到微控制器缓冲区。根据我的时序检查,通过cType调用C++函数大约有代码> 0.45 >代码>秒,在C++侧调用函数使用<代码> 0.17 <代码>秒。我需要设法减少这种差异

以下是相关的python代码,其中数据是点的2D数组,clibrary通过ctypes加载:

data_np = np.vstack([nodes, positions, velocities, times]).transpose().astype(np.long)

data = ((c_long * 4) * N)()
for i in range(N):
    data[i] = (c_long * 4)(*data_np[i])

timer = time()
clibrary.addPvtAll(N, data)
print("clibrary.addPvtAll() call: %f" % (time() - timer))

这里是所谓的C++函数:

void addPvtAll(int N, long data[][4]) {

    clock_t t0, t1;
    t0 = clock();

    for(int i = 0; i < N; i++) {
        unsigned short node = (unsigned short)data[i][0];
        long p = data[i][1];
        long v = data[i][2];
        unsigned char t = (unsigned char)data[i][3];

        VCS_AddPvtValueToIpmBuffer(device(node), node, p, v, t, &errorCode);
    }

    t1 = clock();
    printf("addPvtAll() call: %f \n", (double(t1 - t0) / CLOCKS_PER_SEC));
}
void addPvtAll(int N,long data[][4]){
时钟t0,t1;
t0=时钟();
对于(int i=0;i

我不需要使用cType,但我不想每次运行时都要编译Python代码。

< Python和C++之间的往返行程可能很贵,尤其是在使用cType(这就像是一个普通的C/Python包装器的解释版本)。 你的目标应该是尽量减少每次旅行的次数,并尽可能多地完成每次旅行的工作

在我看来,您的代码的粒度太细了(即,每次旅行做的工作太多,而每次旅行做的工作太少)

numpy包可以直接向C/C++公开其数据。这将使您避免对Python对象进行昂贵的装箱和拆箱(以及伴随而来的内存分配),并允许您一次传递一系列数据点,而不是一个点


修改你的C++代码,每次处理多个点,而不是每次调用一次(就像SqLITE3模块与执行VS执行一样)。

< P>这是我的解决方案,它有效地消除了Python和C.Copyon KyByFang64 SOS之间的测量时差,用于在NUMPY中为C数组提供SWIG和Raymond Hettinger。我在Python中使用一个numpy数组,该数组纯粹作为指针发送到C,在两种语言中访问相同的内存块

除了使用
gettimeofday()
而不是
clock()
之外,C函数保持不变,这会给出不准确的时间:

void addPvtFrame(int pvt[6][4]) {

    timeval start,stop,result;
    gettimeofday(&start, NULL);

    for(int i = 0; i < 6; i++) {
        unsigned short node = (unsigned short)pvt[i][0];
        long p = (long)pvt[i][1];
        long v = (long)pvt[i][2];
        unsigned char t = (unsigned char)pvt[i][3];

        VCS_AddPvtValueToIpmBuffer(device(node), node, p, v, t, &errorCode);
    }

    gettimeofday(&stop, NULL);
    timersub(&start,&stop,&result);
    printf("Add PVT time in C code: %fs\n", -(result.tv_sec + result.tv_usec/1000000.0));
}
最后,我的Python代码通过numpy将
pvt
构造为一个连续数组:

pvt = np.vstack([nodes, positions, velocities, times])
pvt = np.ascontiguousarray(pvt.transpose().astype(int))

timer = time()
xjus.addPvtFrame(pvt)
print("Add PVT time to C code: %fs" % (time() - timer))

在我的机器上,测量的时间现在有大约%1的差异。

您可以使用
数据\u np.data.tobytes()


是C++中的主程序,调用Python代码,或者在Python中调用C++代码。如果主程序在Python中,则应该通过扩展库调用C++,如Python/C API、SWIG、PYCXX或BooST.python。您还可以使用Cython,它允许您从Python中调用C/C++代码。然而,我不想每次运行它时都要编译Python,而且理想地不必重写整个C++库。你建议研究哪一个?Boost.Python和SWIG涉及编写包装器,而不是重写代码。SWIG有时会生成难看的代码,而Boost.Python在64位平台上有问题。如果您确实使用Boost.Python,请创建一个32位Linux虚拟机来运行它。SWIG使用提供的接口文件自动生成包装器。PyCXX看起来有点奇怪,但很有前途。您最好的选择是SWIG和Boost.Python。它们都不需要重写。
pvt = np.vstack([nodes, positions, velocities, times])
pvt = np.ascontiguousarray(pvt.transpose().astype(int))

timer = time()
xjus.addPvtFrame(pvt)
print("Add PVT time to C code: %fs" % (time() - timer))
data_np = np.vstack([nodes, positions, velocities, times]).transpose().astype(np.long)
timer = time()
clibrary.addPvtAll(N, data_np.data.tobytes())
print("clibrary.addPvtAll() call: %f" % (time() - timer))