加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 为什么boost.geometry.index.rtree比superliminal慢.RTree

发布时间:2020-12-16 10:12:00 所属栏目:百科 来源:网络整理
导读:我测试了boost.geometry.index.rtree(boost 1.59 www.boost.org)和superliminal.RTree( http://superliminal.com/sources/sources.htm#C_Code). 令我惊讶的是,superliminal.RTree比boost.geometry.index.rtree更快. 环境设置 将相同的空间索引数据添加到supe
我测试了boost.geometry.index.rtree(boost 1.59 www.boost.org)和superliminal.RTree( http://superliminal.com/sources/sources.htm#C_Code).

令我惊讶的是,superliminal.RTree比boost.geometry.index.rtree更快.

环境设置

>将相同的空间索引数据添加到superliminal.RTree和
boost.geometry.index.rtree对象.
>测试相同的空间索引查询100次并获得消耗的时间.
> GCC版本是“gcc版本4.4.6 20110731(Red Hat 4.4.6-4)(GCC)”,使用“-g -o2 -Wall -finline-functions”编译器标志.
>使用RTree< uint64_t,int,2,int64_t>

提升代码

namespace bg = boost::geometry; 
namespace bgi = boost::geometry::index; 

typedef bg::model::point < int,bg::cs::cartesian > point_t; 
typedef bg::model::box < point_t > box_t; 
typedef std::pair < box_t,uint64_t > value_t; 
typedef bgi::rtree < value_t,bgi::quadratic < 8,4 > > rtree_t;

结果是:

superliminal.RTree 0.029s

boost.geometry.index.rtree 0.12s.

解决方法

很难说为什么它在你的情况下更慢,因为你没有共享代码,也没有告诉我们如何使用两个R-tree实现.您还没有提供有关您正在存储的数据的任何信息.当您比较算法或数据结构时,这些事情非常重要.

我只能猜测你使用的是Superliminar R-tree,就像它在附加的测试文件中使用的那样,所以你将回调函数传递给搜索成员函数.我猜你正在使用Boost.Geometry R-tree,就像它在“快速入门”部分的文档中所示的那样,所以你将std :: back_insert_iterator的对象传递给查询成员函数.那么我们来看看吧.

#include "RTree.h"

#include <vector>

#include <boost/geometry.hpp>
#include <boost/geometry/index/rtree.hpp>

#include <boost/timer.hpp>

struct Rect
{
  Rect()  {}

  Rect(int a_minX,int a_minY,int a_maxX,int a_maxY)
  {
    min[0] = a_minX;
    min[1] = a_minY;

    max[0] = a_maxX;
    max[1] = a_maxY;
  }

  int min[2];
  int max[2];
};

// used with Superliminar R-tree
std::vector<uint64_t> res;
bool MySearchCallback(uint64_t id,void* arg)
{
    res.push_back(id);
    return true;
}

int main()
{
    // randomize rectangles
    std::vector<Rect> rects;
    for (size_t i = 0 ; i < 300000 ; ++i)
    {
        int min_x = rand() % 10000;
        int min_y = rand() % 10000;
        int w = 1 + rand() % 100;
        int h = 1 + rand() % 100;
        rects.push_back(Rect(min_x,min_y,min_x+w,min_y+h));
    }

    // create the rectangle passed into the query
    Rect search_rect(4000,4000,6000,6000);

    // create the Superliminar R-tree
    RTree<uint64_t,int64_t> tree;

    // create the Boost.Geometry R-tree
    namespace bg = boost::geometry;
    namespace bgi = boost::geometry::index;
    typedef bg::model::point<int,bg::cs::cartesian> point_t;
    typedef bg::model::box<point_t> box_t;
    typedef std::pair<box_t,uint64_t> value_t;
    bgi::rtree<value_t,bgi::quadratic<8,4> > bg_tree;

    // Insert values
    for(size_t i = 0; i < rects.size(); i++)
    {
        Rect const& r = rects[i];
        tree.Insert(r.min,r.max,i);

        box_t b(point_t(r.min[0],r.min[1]),point_t(r.max[0],r.max[1]));
        bg_tree.insert(value_t(b,i));
    }

    // test Rtree
    {
        int sum = 0;
        boost::timer t;
        for (size_t i = 0 ; i < 100 ; ++i)
        {
            res.clear();
            sum += tree.Search(search_rect.min,search_rect.max,MySearchCallback,NULL);
        }
        double s = t.elapsed();
        std::cout << s << " " << sum << std::endl;
    }

    // test BG Rtree
    {
        box_t search_box(
            point_t(search_rect.min[0],search_rect.min[1]),point_t(search_rect.max[0],search_rect.max[1]));
        size_t sum = 0;
        boost::timer t;
        for (size_t i = 0 ; i < 100 ; ++i)
        {
            std::vector<value_t> res;
            sum += bg_tree.query(bgi::intersects(search_box),std::back_inserter(res));
        }
        double s = t.elapsed();
        std::cout << s << " " << sum << std::endl;
    }
}

结果(使用GCC 4.8 -O2 -finline-functions)是:

0.014s for Superliminar R-tree
0.072s for Boost.Geometry R-tree

所以它们与你的相似,即一个快5倍.请注意,在这两种情况下,我都创建了一个存储结果的容器(Superliminar的ID和Boost.Geometry的整个值).问题是R树的使用方式不同.

优化1

让我们试着通过以相同的方式存储相同的结果来消除两个R树的使用差异.为了做到这一点,删除临时std :: vector< value_t>.要实现回调,请将std :: back_insert_iterator替换为名为boost :: function_output_iterator的函数对象.在这两种情况下,只存储std :: vector< uint64_t>中的ID.并希望编译器优化代码.

#include "RTree.h"

#include <vector>

#include <boost/function_output_iterator.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/index/rtree.hpp>

#include <boost/timer.hpp>

struct Rect
{
  Rect()  {}

  Rect(int a_minX,int a_maxY)
  {
    min[0] = a_minX;
    min[1] = a_minY;

    max[0] = a_maxX;
    max[1] = a_maxY;
  }

  int min[2];
  int max[2];
};

std::vector<uint64_t> res;

// used with Superliminar R-tree
bool MySearchCallback(uint64_t id,void* arg)
{
    res.push_back(id);
    return true;
}

// used with Boost.Geometry R-tree
struct MySearchCallback2
{
    template <typename Value>
    void operator()(Value const& v)
    {
        res.push_back(v.second);
    }
};

int main()
{
    // randomize rectangles
    std::vector<Rect> rects;
    for (size_t i = 0 ; i < 300000 ; ++i)
    {
        int min_x = rand() % 10000;
        int min_y = rand() % 10000;
        int w = 1 + rand() % 100;
        int h = 1 + rand() % 100;
        rects.push_back(Rect(min_x,search_rect.max[1]));
        size_t sum = 0;
        MySearchCallback2 callback;
        boost::timer t;
        for (size_t i = 0 ; i < 100 ; ++i)
        {
            res.clear();
            sum += bg_tree.query(bgi::intersects(search_box),boost::make_function_output_iterator(callback));
        }
        double s = t.elapsed();
        std::cout << s << " " << sum << std::endl;
    }
}

在这种情况下,结果是:

0.014s for Superliminar R-tree
0.033s for Boost.Geometry R-tree

优化2

可以做的另一件事是禁用断言. Boost.Geometry R-tree中有一些.用-DNDEBUG编译代码后,结果更接近:

0.014s for Superliminar R-tree
0.015s for Boost.Geometry R-tree

结论

在该综合测试案例中,对于随机数据等,结果或多或少相同.再说一次,对你来说,他们可能会有所不同,我不知道你在做什么,所以我无法告诉你这是什么问题.

这是一个非常简单的用例,如果测试更复杂的用例,结果可能会有所不同.换句话说,应该分析一个真实的应用程序,看看是否存在一些瓶颈.

此外,Boost.Geometry R-tree的代码要复杂得多.两个R树实现的接口是不同的,特别是搜索/查询功能都需要不同的参数,并且大多数肯定以不同的方式处理它们.编译器可以选择以不同方式优化代码.

附:

使用Boost.Geometry R-tree,可以使用不同的分割算法和打包算法,以便您可以尝试哪种方法最适合您的情况.要使用打包算法,您必须将一系列值传递给rtree构造函数.对于相同的数据和元素的数量以及使用打包算法创建的rtree,查询时间对我来说是0.005秒.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读