有没有一种方法可以使此代码更快?

时间:2018-08-28 16:20:08

标签: c++ performance c++11

我有一个C ++结构,需要将其转换为列表,以便可以加载到GPU

struct point_cloud_tensor
{
    std::vector<float>               timestamp;
    std::vector<std::vector<double>>  position;
    // more fields
};


point_cloud_tensor sweep_to_array(const point_sweep &point_sweep)
{
    const auto         num_points = point_sweep.points.size();
    point_cloud_tensor tensor;

    point_cloud_tensor.timestamp.reserve(num_points);
    point_cloud_tensor.point.reserve(num_points);

    for (int i = 0; i < point_sweep.points.size(); i++)
    {
        const auto point = point_sweep.points.at(i);
        tensor.timestamp.push_back(point.timestamp);

        std::vector<double> point_triple(3);
        point_triple.push_back(point.x);
        point_triple.push_back(point.y);
        point_triple.push_back(point.z);
        tensor.position.push_back(point_triple);
        // more fields
    }

    return tensor;
}

扫描矢量中大约有10万个点,运行时间约为30毫秒。

有没有办法大幅度减少这种情况?

3 个答案:

答案 0 :(得分:1)

在这种情况下,您的std::vector用于小型阵列,为此,您可以将其替换为std:array 如前所述,测试代码的运行速度取决于硬件,因此我无法100%确定此更改是否会更快。

答案 1 :(得分:0)

如果大小不变,请勿每次都调用size()

由于您已经将point_sweep.points.size()存储到变量num_points中,因此可以在for循环中使用它。当您这样迭代时:

for (int i = 0; i < point_sweep.points.size(); i++)

每次迭代时,您都将取消引用point_sweep和取消引用points以调用其方法size()。改用局部变量应该更快:

for (int i = 0; i < num_points; i++)

在适当时使用参考

获取观点时:

const auto point = point_sweep.points.at(i);

您无缘无故在调用复制构造函数。您应该使用对它的引用,使用&

const auto& point = point_sweep.points.at(i);

引用可能会有风险,因为您执行的每次修改都会应用于原始对象,但是由于您使用的是const reference,因此应该是安全的。

将元素推到向量的后面时,将调用降到最低

填写tensor.position向量后,您可以:

  1. 使用intializer_list
  2. 创建点
  3. 添加没有临时变量的项目,以便于移动

因此,此代码:

std::vector<double> point_triple(3);
point_triple.push_back(point.x);
point_triple.push_back(point.y);
point_triple.push_back(point.z);
tensor.position.push_back(point_triple);

成为:

tensor.position.push_back({point.x, point.y, point.z});

在我看来,它变得更容易阅读。

使用其他3D点结构(如果可能)

此外,正如其他人指出的那样,如果您可以更改数据结构,则可以使用std::arraystd::tuple,也可以简单地编写诸如struct Point { double x, y, z; }之类的结构。几乎可以像访问向量一样访问数组,这应该使转换更容易一些。该元组必须由std :: get访问,这需要重写一些代码。例如,如果要显示最后一个元素的内容:

struct point_cloud_tensor
{
    std::vector<float>                            timestamp;
    std::vector<std::tuple<double,double,double>> position;
    // more fields
} tensor;
auto last_pos = tensor.position.back();
std::cout << "x=" << std::get<0>(last_pos) << ' ';
std::cout << "y=" << std::get<1>(last_pos) << ' ';
std::cout << "z=" << std::get<2>(last_pos) << std::endl;

但是,通过元组,您可以使用emplace_back而不是push_back添加项目,这样可以节省移动构造函数,例如:

tensor.position.emplace_back(point.x, point.y, point.z);

请注意语法上的差异。使用push_back,您有一个参数{point.x, point.y, point.z},但是使用emplace_back,您有3个参数point.x, point.y, point.z。基本上,使用emplace_back只是删除花括号。

答案 2 :(得分:0)

您是否考虑过在构造点时退后一步并创建列表?