gpt4 book ai didi

使用 Boost Python 的 Python 性能没有 boost

转载 作者:搜寻专家 更新时间:2023-10-31 01:46:01 24 4
gpt4 key购买 nike

我正在从事一个大型计算机视觉项目,我需要对来自多个摄像头的每一帧进行一些处理。它很重,我想 boost 速度。所以我想到使用 boost python 在 c++ 中包装一个 python 函数。

这里是我想用 C++ 包装的函数:

def computeSumInboundingbox(self, cameraTable, integral):   
for line in cameraTable:
minX, minY, maxX, maxY = line[2], line[3], line[4], line[5]
# sum of the pixel in the bounding box according to integral image
sumBox = integral[(minY,minX)] + integral[(maxY, maxX)] - integral[(maxY,minX)] - integral[(minY,maxX)]
# we scale the sumBox
if sumBox != 0:
self.bitmap[line[0],line[1]] = \
float(sumBox) / ((maxX - minX) * (maxY - minY))

此函数正在从 2D 列表 cameraTable(查找表)中读取一些坐标。该表已在我的类(class)初始化期间加载。 Integralbitmap 是二维 numpy 数组。我有很多坐标,所以每一帧都这样做有点慢。

然后我用 C++ 包装函数。

boost::python::numeric::array computeSumInboundingbox(boost::python::numeric::array integral, list cameraTable, boost::python::numeric::array bitmap)
{
list currCameraTable;
float sumBox;
for (int i = 0 ; i < len(cameraTable) ; i++)
{
int x = extract<float>(cameraTable[i][0]);
int y = extract<float>(cameraTable[i][1]);
float minX = extract<float>(cameraTable[i][2]);
float minY = extract<float>(cameraTable[i][3]);
float maxX = extract<float>(cameraTable[i][4]);
float maxY = extract<float>(cameraTable[i][5]);

// // sum of the pixel in the bounding box according of integral image
sumBox = extract<float>(integral[make_tuple(minY, minX)] + integral[make_tuple(maxY, maxX)] -
integral[make_tuple(maxY, minX)] - integral[make_tuple(minY, maxX)]);
// we scale the sumBox
if (sumBox != 0)
bitmap[make_tuple(y,x)] = sumBox / ((maxX - minX) * (maxY - minY));
}

return bitmap;
}

但是我的表现非常糟糕,一个 2000 帧的视频运行了 45 秒!

然后我认为提取函数可能需要一段时间才能处理,所以首先我在 python 中将我的 2D 列表转换为 1D std::vector(我没有真正找到创建 2D vector 的方法)

boost::python::numeric::array computeSumInboundingbox(boost::python::numeric::array integral, std::vector<float> cameraTable, boost::python::numeric::array bitmap)
{
list currCameraTable;
float sumBox;
int x;
int y;
float minX, minY, maxX, maxY;

for (int i = 0 ; i < cameraTable.size() ; i+=6)
{
int x = cameraTable[i];
int y = cameraTable[i+1];
float minX = cameraTable[i+2];
float minY = cameraTable[i+3];
float maxX = cameraTable[i+4];
float maxY = cameraTable[i+5];

// // sum of the pixel in the bounding box according of integral image
sumBox = extract<float>(integral[make_tuple(minY, minX)] + integral[make_tuple(maxY, maxX)] -
integral[make_tuple(maxY, minX)] - integral[make_tuple(minY, maxX)]);
// we scale the sumBox
if (sumBox != 0)
bitmap[make_tuple(y,x)] = sumBox / ((maxX - minX) * (maxY - minY));
}

return bitmap;
}

仅供引用:

BOOST_PYTHON_MODULE(Mapper_ext)
{
using namespace boost::python;
using namespace std;

boost::python::numeric::array::set_module_and_type("numpy", "ndarray");

class_<vector<float> >("VectorFloat")
.def(vector_indexing_suite<vector<float> > ());

def("computeSumInboundingbox", computeSumInboundingbox);
}

下面是三个函数对2000帧的处理时间

  • python 函数 = 100s
  • 第一个 C++ 函数 = 145 秒
  • 第二个 c++ 函数 = 121s

即使第二个 c++ 函数比第一个好,它仍然比只使用 python 慢。为什么?我认为使用 C++ 会更快,尤其是使用 for 循环。无论如何我可以让 c++ 比 python 执行得更快,还是我在这里浪费时间?

这是我的 numba 版本。一开始,我的 createFloorBitmap 方法在我的类中,我将 numba 装饰器添加到类中,但我无法让它工作,所以我将该方法移出了类。 setup() 和 execute() 继承自对象 Node。

class Mapper(Node):
def setup(self):
# initialise some parameters self.bitmap, self.coordTable
def execute(self,data):
# main function
integral = data['image']
self.bitmap[:] = 0
self.bitmap = createFloorBitmap(self.bitmap, self.coordTable, integral)
return self.bitmap

@jit(f8[:,::1](f8[:,::1], f8[:,::1], f8[:,::1]))
def createFloorBitmap(bitmap, lines, integral):
for row in range(lines.shape[0]):
minX, minY, maxX, maxY = lines[row, 2], lines[row, 3], lines[row, 4], lines[row, 5]
sumBox = integral[minY,minX] + integral[maxY, maxX] - integral[maxY,minX] - integral[minY,maxX]
if sumBox != 0:
bitmap[lines[row, 1],lines[row, 0]] = float(sumBox) / ((maxX - minX) * (maxY - minY))
return bitmap

谢谢你的帮助

最佳答案

可以通过使用数组作为索引来 boost 速度,代码如下:

w = 600

integral = np.random.randint(0, 255, (w, w))
bitmap = np.zeros_like(integral)

lines = np.random.randint(0, w, (10000, 6))

def computeSumInboundingbox(bitmap, cameraTable, integral):
for line in cameraTable:
minX, minY, maxX, maxY = line[2], line[3], line[4], line[5]
sumBox = integral[(minY,minX)] + integral[(maxY, maxX)] - integral[(maxY,minX)] - integral[(minY,maxX)]
if sumBox != 0:
bitmap[line[0],line[1]] = float(sumBox) / ((maxX - minX) * (maxY - minY))

def computeSumInboundingbox2(bitmap, line, integral):
tx, ty, minx, miny, maxx, maxy = line.T
sumBox = integral[miny, minx] + integral[maxy, maxx] - integral[maxy, minx] - integral[miny, maxx]
mask = sumBox != 0
bitmap[tx[mask], ty[mask]] = (sumBox.astype(float)[mask] / ((maxx - minx) * (maxy - miny))[mask])

bitmap1 = np.zeros_like(integral)
bitmap2 = np.zeros_like(integral)
computeSumInboundingbox(bitmap1, lines, integral)
computeSumInboundingbox2(bitmap2, lines, integral)
print np.allclose(bitmap1, bitmap2)

现在是时间:

computeSumInboundingbox: 10 loops, best of 3: 42.4 ms per loop
computeSumInboundingbox2: 100 loops, best of 3: 2.36 ms per loop

为什么 c++ 很慢,因为你使用 python 对象级方法来进行数组索引。你可以使用 cython,它知道如何在 c 级访问数据。

编辑

这是一个 numba 版本:

import numba
@numba.jit("void(i4[:,::1], i4[:,::1], i4[:,::1])")
def computeSumInboundingbox3(bitmap, lines, integral):
for row in range(lines.shape[0]):
minX, minY, maxX, maxY = lines[row, 2], lines[row, 3], lines[row, 4], lines[row, 5]
sumBox = integral[minY,minX] + integral[maxY, maxX] - integral[maxY,minX] - integral[minY,maxX]
if sumBox != 0:
bitmap[lines[row, 0],lines[row, 1]] = float(sumBox) / ((maxX - minX) * (maxY - minY))

和速度:

10000 loops, best of 3: 119 µs per loop

关于使用 Boost Python 的 Python 性能没有 boost ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21249851/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com