暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

项目经验分享:Milvus 编译优化

开源之夏 2021-09-02
1609


暑期 2021 项目研发正在火热进行中,开源之夏公众号面向广大社区及项目承担学生征稿,欢迎大家热情分享!

发送投稿文章至官方联络邮箱:

summer@iscas.ac.cn

添加公众号小编微信投稿:

本期分享来自 Milvus 社区沈志同学带来的项目(Compilation optimization of Knowhere)经验。


目名称

Compilation optimization of Knowhere


目综述

Milvus 是一款开源的向量数据库,支持针对 TB 级向量的增删改操作和近实时查询,具有高度灵活、稳定可靠以及高速查询等特点。Milvus 集成了 Faiss、NMSLIB、Annoy 等广泛应用的向量索引库,提供了一整套简单直观的 API,可以针对不同场景选择不同的索引类型。此外,Milvus 还可以对标量数据进行过滤,进一步提高了召回率,增强了搜索的灵活性。


Knowhere 是 Milvus 做向量索引和查询的核心 C++ 库,使用 CMake 编译。


本次项目需求是优化Knowhere库的编译部分,使得Knowhere能独立于milvus进行编译并优化knowhere第三方库编译流程,减少重复编译库情况,提高编译文件可读性。


目步骤

 明确Knowhere和milvus交叉编译内容。

修改Knowhere第三方库编译代码,将Knowhere中用到的milvus第三方库独立写到Knowhere的编译文件中。

■ 改写knowhere/cmake下的编译文件,该文件将编译选项和第三方库编译耦合在一起,使编译文件难以阅读和修改;调整文件结构,使编译文件可读性更强。


目实施


#1

明确Knowhere和milvus交叉编译内容

Milvus的第三方库编译:milvus的第三方库编译是可读性比较强的,库编译选项定义在

cmake/ThirdPartyPackages.cmake文件夹下,库的编译位于thirdparty文件夹下,每个库的编译文件单独写成CMakeLists文件放在thirdparty相对应的子文件夹下。


整体编译位于core/CMakeLists中,CmakeLists文件会首先调用cmake文件夹下的.cmake文件对编译选项进行定义,随后通过add_subdirectory引入第三方库的编译文件,具体的第三方库编译由thirdparty下的子文件夹进行统筹。

Figure 1 milvus文件结构


Figure 2 milvus第三方库编译


knowhere的第三方库编译:相比于milvus的编译,knowhere的编译集中在

cmake/ ThirdPartyPackagesCore.cmake文件中,编译文件冗长,阅读困难,库与库之间的依赖表现不明显,不利于用户使用和调整。

另外可以发现knowhere不仅依赖于外层的log,utils源码,还依赖boost_ext,fiu,gtest,google_benchmark等相关库以及一部分写在milvus中的源码。现在Knowhere的编译中,会调用父目录下的这部分代码和knowhere中需要编译的对象进行链接,我们在Knowhere的文件夹下增加了这部分文件并修改CMakeLists中的代码,添加对这部分所需库的编译过程。

Figure 3 knowhere的第三方库编译


knowhere中部分对milvus编译库依赖如下:  

set (LOG_SRC
knowhere/common/Log.cpp
${MILVUS_THIRDPARTY_SRC}/easyloggingpp/easylogging++.cc
)
add_library(index_log STATIC ${LOG_SRC})
set_target_properties(index_log PROPERTIES RULE_LAUNCH_COMPILE "")
set_target_properties(index_log PROPERTIES RULE_LAUNCH_LINK "")
include_directories(${MILVUS_THIRDPARTY_SRC})


set(config_srcs
knowhere/archive/KnowhereConfig.cpp
        )


我们对knowhere增加这部分库的编译内容,使knowhere有能力单独对这部分库进行编译。

Figure 4 调整前后Knowhere文件夹结构。

其中左图是调整前index目录结构,右图为调整后目录结构。


添加编译库代码如下,这里add_subdirectory会自动调用该文件夹下的CMakeLists.txt内容。

# ****************************** Thirdparty googletest ***************************************
if ( KNOWHERE_BUILD_TESTS )
if(NOT TARGET gtest)
add_subdirectory( gtest )
add_subdirectory( google_benchmark)
endif()
endif()
# ****************************** Thirdparty Arrow ***************************************
if(NOT TARGET boost_bitset_ext)
add_subdirectory( boost_ext )
endif()
if(NOT TARGET fiu)
add_subdirectory(fiu)
endif()


#2

修改Knowhere第三方库编译代码以避免重复编译情况

Milvus依赖于Knowhere库,且两部分有一部分编译内容交叉,之前的编译会将milvus中编译好的内容链接到knowhere需要的文件里,在给knowhere增加独立编译的功能后,两者之间的编译会出现重复编译的过程,也即milvus已经编译好的内容,knowhere会再次编译一遍,这种情况和我们优化编译流程的初衷背离。通过if(NOT TARGET)保证了一部分库在系统能够找到情况下不再重复进行编译,但因为作用域的问题,一些库可能并不能在index/thirdparty文件夹下找到(之前编译集中在index/cmake文件夹下进行)所以还需要进一步对一些库文件的property进行调整。

set_target_properties(
faiss
PROPERTIES
IMPORTED_GLOBAL TRUE
IMPORTED_LOCATION "${FAISS_STATIC_LIB}"
INTERFACE_INCLUDE_DIRECTORIES "${FAISS_INCLUDE_DIR}"
    )


#3

明确Knowhere和milvus交叉编译内容

这个问题主要出现在faiss库的编译上,faiss库依赖于openblas库进行编译。之前Knowhere第三方库的编译集中在一个文件下进行,尽管文件冗长,难以理解和维护,但所有需要编译的库都处于同一作用域当中,通过给External_project增加dependency方式就可以依赖问题。但在修改编译代码之后,faiss和OpenBLAS的编译被分配到了各自的文件夹下由父目录thirdparty下的CMakeLists进行调用,两个文件夹平行,不再能通过add_dependency方式添加依赖。


最后是通过将Openblas的编译保留在cmake文件夹下,而faiss的编译修改到thirdparty目录下进行解决的,这样保证了openblas和faiss的编译仍位于同一作用域,可以为两边的库添加依赖。


第三方库的编译依赖关系定义如下:

if(NOT OpenBLAS_FOUND)
message(STATUS "OpenBLAS FOUNDED")
ExternalProject_Add_StepDependencies(faiss_ep configure openblas_ep)
    endif()


证优化后编译效果


#1

Knowhere的独立编译

Figure 5 Knowhere独立编译成功


#2

Milvus下的编译

Figure 6 Milvus编译成功。对比修改index下内容前后,无target重复编译情况产生


目规划

 升级 CMake 版本,通过下载路径可配置等方式加速编译流程。

优化编译选项并形成文档。

除此以外编译代码本身还有很多细节没有考虑到,比如一些带有MILVUS的变量还留存在 knowhere 的编译代码中。这些细节在结项前需要去解决掉。



在此要对Goose老师对我的指导进行致谢,在项目进行的过程中Goose老师耐心细致的帮我解决了很多很多问题。我自己并不是很熟悉cmake和编译,而且国内这方面的资料又比较少,一开始在github上找了一个cmake的教程也只是简单了解了一些常见用法,实际运用到项目中的时候是有很多不足的,这里Goose真的帮了很大忙,每次回复都特别及时,而且往往能一针见血的找到问题出在哪里。


通过这次项目我学到了很多cmake相关的知识,对编译也有了很深入的了解,使我得到了很大的成长和进步,也希望大家能多多关注Milvus社区,相信一定能有所收获。



文章转载自开源之夏,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论