Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.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++ 在C+中存储、加载和使用反向索引的最佳方法+;(约500个月)_C++_Performance_Data Structures_Inverted Index - Fatal编程技术网

C++ 在C+中存储、加载和使用反向索引的最佳方法+;(约500个月)

C++ 在C+中存储、加载和使用反向索引的最佳方法+;(约500个月),c++,performance,data-structures,inverted-index,C++,Performance,Data Structures,Inverted Index,我正在开发一个使用TF-IDF和余弦相似性的小型搜索引擎。当添加页面时,我会建立一个反向索引,以保持不同页面中的单词频率。我删除了停止词和更常见的词,复数/动词/等词干 我的倒排索引如下所示: map< string, map<int, float> > index [ word_a => [ id_doc=>frequency, id_doc2=>frequency2, ... ], word_b => [ id_doc->

我正在开发一个使用TF-IDF和余弦相似性的小型搜索引擎。当添加页面时,我会建立一个反向索引,以保持不同页面中的单词频率。我删除了停止词和更常见的词,复数/动词/等词干

我的倒排索引如下所示:

map< string, map<int, float> > index

[
    word_a => [ id_doc=>frequency, id_doc2=>frequency2, ... ],
    word_b => [ id_doc->frequency, id_doc2=>frequency2, ... ],
    ...
]
然后我在搜索时加载它:

ifstream ifs_index("index.sr", ios::binary);
boost::archive::bynary_iarchive ia(ifs_index);
ia >> index;
但是它的速度非常慢,加载需要10秒的时间

  • 我不知道
    map
    对于反向索引是否足够有效

  • 为了对文档进行聚类,我从每个文档中获取所有关键字,并循环使用这些关键字对类似的文档进行评分,但我希望避免再次阅读每个文档,而只使用这个反向索引。但我认为这种数据结构将是昂贵的

  • 提前感谢您的帮助

    答案在很大程度上取决于您是否需要支持与机器RAM相当或更大的数据,以及在您的典型用例中,您是否可能访问所有索引数据,或者只访问其中的一小部分

    如果您确信您的数据将适合您的机器的内存,您可以尝试优化您现在使用的基于地图的结构。将数据存储在地图中应该可以提供相当快的访问速度,但是当您将数据从磁盘加载到内存中时,总会有一些初始开销。此外,如果只使用索引的一小部分,这种方法可能会非常浪费,因为您总是读取和写入整个索引,并将其全部保存在内存中

    下面我列出了一些您可以尝试的建议,但是在您花太多时间去做这些建议之前,请确保您确实衡量了哪些改进了负载和运行时间,哪些没有。如果不在您使用的实际数据上分析实际工作代码,这些只是猜测,可能是完全错误的

    • map
      实现为一棵树(通常为黑红树)。在许多情况下,
      hash_映射
      可能会为您提供更好的性能和更好的内存使用(例如,更少的分配和更少的碎片)
    • 尝试减小数据的大小—更少的数据意味着从磁盘读取数据会更快,可能会减少内存分配,有时由于更好的局部性,内存性能会更好。例如,您可以考虑使用<代码>浮点来存储频率,但也许您只能将发生次数作为“代码”>未签名的短存储在MAP值中,并且在单独的映射存储中存储每个文档的所有单词的数量(也都是一个简短的)。使用这两个数字,您可以重新计算频率,但在将数据保存到磁盘时使用更少的磁盘空间,这可能导致更快的加载时间
    • 您的映射有很多条目,在这种情况下,有时使用自定义内存分配器有助于提高性能

    如果您的数据可能会超出计算机RAM的大小,我建议您使用内存映射文件来存储数据。这种方法可能需要重新建模您的数据结构,或者使用自定义STL分配器,或者使用完全自定义的数据结构,而不是
    std::map
    ,但如果做得好,可能会提高性能一个数量级。特别是,这种方法使您不必一次将整个结构加载到内存中,因此您的启动时间将显著提高,但代价是,当您第一次接触结构的不同部分时,会出现与磁盘访问相关的轻微延迟。主题相当广泛,需要对代码进行更深入的更改,而不仅仅是调整地图,但是如果您计划处理大量数据,您当然应该看看
    mmap
    和朋友。

    谢谢您的回答,我设法用
    无符号short int
    而不是频率的float来大幅减小索引的大小。
    ifstream ifs_index("index.sr", ios::binary);
    boost::archive::bynary_iarchive ia(ifs_index);
    ia >> index;