2

我正在研究如何使基于libosmium的项目使用多线程解析 OpenStreetMap PBF 区域。解析节点、方式或关系是多线程的,但解析区域不是。

例如,在运行以下计算关系的代码时,top显示 CPU 利用率超过 400%:

#include <osmium/handler.hpp>
#include <osmium/io/pbf_input.hpp>
#include <osmium/visitor.hpp>

using namespace osmium;

struct MyHandler : public handler::Handler {
    int counter = 0;
    void relation(const Relation &relation) {
        counter++;
    }
};

int main(int argc, char *argv[]) {
    io::File infile(argv[1]);
    MyHandler handler;
    io::Reader reader(infile);
    apply(reader, handler);
    reader.close();
    std::cout << handler.counter << "\n";
}

当我修改它以计算区域时,CPU 保持在 100% 左右:

#include <osmium/area/assembler.hpp>
#include <osmium/area/multipolygon_collector.hpp>
#include <osmium/handler/node_locations_for_ways.hpp>
#include <osmium/index/map/sparse_mem_array.hpp>
#include <osmium/io/pbf_input.hpp>

using namespace osmium;

using index_type = index::map::SparseMemArray<unsigned_object_id_type, Location>;
using cache_type = handler::NodeLocationsForWays<index_type>;

struct MyHandler : public handler::Handler {
    int counter = 0;
    void area(const Area &area) {
        counter++;
    }
};

int main(int argc, char *argv[]) {
    // pass 1
    io::File infile(argv[1]);
    area::Assembler::config_type assembler_config;
    area::MultipolygonCollector<area::Assembler>  collector(assembler_config);
    io::Reader reader1(infile, osm_entity_bits::relation);
    collector.read_relations(reader1);
    reader1.close();
    // pass 2
    index_type index;
    cache_type cache{index};
    cache.ignore_errors();
    MyHandler handler;
    io::Reader reader2(infile);
    apply(reader2, cache, collector.handler([&handler](
        const memory::Buffer &&buffer) { apply(buffer, handler); }));
    reader2.close();
    std::cout << handler.counter << "\n";
}

这里的不同之处在于代码在 2 遍中运行。第一遍从关系中组装区域引用,然后第二遍使用节点缓存和收集的关系数据构建区域。但是,这样的结构似乎不是多线程的。

我怎样才能使它利用多个线程?libosmium 中是否已经内置了现有方法,或者我应该开始实现自己的线程池和队列?

4

0 回答 0