上文《Milvus 最佳实践之如何选择索引类型》针对0.5.3版本和不同用户需求提出了选择索引类型的意见。本文对Milvus0.6.0版本的部分关键系统配置项进行了详细的说明和测试验证,并给出了设置建议。系统配置项是Milvus在启动服务时进行的参数设置,需要在Milvusdocker镜像启动前修改server_config.yaml文件。下面我们详细介绍几个影响性能的重要参数:cpu_cache_capacitycpu_cache_capacity用于限制Milvus运行过程中用于缓存向量(索引)数据的内存量,单位为GB。设置这个值的时候要根据数据量来考虑。如何计算数据量?有两种类型的数据:原始矢量数据。在建立索引之前,搜索是基于原始数据的暴力搜索。所需的内存量是原始向量的总数据量。矢量的每个维度都用浮点数表示。我们知道每个float类型占用4个字节,所以总数据量可以按照这个公式计算:4*向量维数*向量条目总数。索引数据,建立索引后,会根据索引进行查找,所以此时需要的内存量就是索引的数据量。不同的索引占用不同大小的空间。对于IVFLAT,其数据量基本等于原始向量的总数据量;对于SQ8,其数据量约为原始向量总数据量的30%。所以要根据情况设置cpu_cache_capacity,使其大于搜索所需的数据量(前提是机器内存足够),搜索性能最好。但也不需要太大,因为内存足够后增加该值不会引起性能的变化。反之,如果设置值小于数据量,Milvus会花费大量时间在内存数据的替换上,严重影响查询性能。关于内存数据的替换,这里解释一下:Milvus将矢量数据批量保存在磁盘上。默认情况下,每个数据文件为1GB。假设我们有10GB的数据,将其分成10个数据文件。假设cpu_cache_capacity设置为5GB。当搜索开始时,文件数据会被一个一个地加载到内存中等待计算。当加载第五个文件时,缓存空间已满。当加载第六个文件时,发现空间不够,于是Milvus将加载第一个文件的数据从内存中删除,从磁盘中加载第六个文件数据,从而保证缓存空间不会超过cpu_cache_capacity设置的值。与索引操作相比,磁盘读取是一个比较耗时的操作,因此应尽量避免内存数据替换。那么,让我们看看如何确定一个合理的cpu_cache_capacity值。例如,假设导入1000万个向量,每个向量的维度为256,则每个向量占用:256*4=1024字节(1KB)。原始向量中的数据总量为:1000万*1KB=10GB。如果没有创建索引,那么cpu_cache_capacity的值应该设置为大于10,这样所有的原始向量数据都会被加载到内存中而不进行替换。如果建立了索引,对于IVFLAT,cpu_cache_capacity的值也应该设置为大于10;对于SQ8,数据量约为3GB,所以cpu_cache_capacity设置为4就可以了。下面是使用公共数据集sift1b的5000万条数据测试cpu_cache_capacity,索引类型为SQ8。这个数据集有5000万个向量,向量维度为128,我们建立了SQ8索引,所以查询需要的数据量为5000万*128*4*0.3=7.5GB。我们分别设置cpu_cache_capacity为4GB、10GB、50GB,使用相同的查询参数进行查询。性能对比如下表所示:从上图可以看出,在CPU和GPU模式下,对于大于索引大小(10G和50G)的cpu_cache_capacity值,搜索速度基本一致;当该参数的值设置为4G时,由于频繁更换内存数据,搜索性能下降了两个数量级。use_blas_thresholdMilvus在搜索时,会调用faiss库的底层函数来计算向量距离。对于使用CPU的计算,faiss库提供了两种计算方式:使用OpenBLAS计算库直接使用CPU指令集根据我们的经验,使用CPU指令集的性能会更好,但是在相同的搜索条件下,有可能在前后两次的耗时差是两倍的情况下,比如前一次0.1秒,后一次0.2秒,我们称这种性能抖动。使用OpenBLAS库性能稍差,尤其是nq比较小的时候,性能会比CPU指令集慢(可能慢两倍以上),但是性能不会抖动,而且耗时相同搜索条件下的多个查询基本相同。使用哪种计算方法取决于use_blas_threshold的值和搜索参数nq(目标向量的数量)。如果nq大于或等于use_blas_threshold,则使用OpenBLAS库。如果nq小于use_blas_threshold,则使用CPU指令集。下面是使用公共数据集sift1b的5000万条数据对use_blas_threshold的测试,索引类型为SQ8:从图中可以看出,在CPU模式下,如果将use_blas_threshold的值设置为1100,则所有测试nq都小于这个值,使用CPU指令集,其查询性能基本呈线性增长,性能较好。当use_blas_threshold设置为500时,可以明显观察到nq=500之前的测试结果和1100差不多,nq大于500之后,因为使用了OpenBLAS库,性能慢了好几倍;在纯GPU模式下,由于计算是在GPU中进行的,与CPU无关,所以use_blas_threshold的取值不会影响搜索性能。在GPU模式下,gpu_search_threshold实际上可以使用CPU来查询,使用哪个设备是由gpu_search_threshold和nq决定的。如果nq大于等于gpu_search_threshold,则使用GPU进行搜索;如果nq小于gpu_search_threshold,则使用CPU进行搜索。为什么GPU模式也提供了CPU计算的选项?这是因为使用GPU进行搜索时,需要将数据从显存复制到显存,而这一步需要一定的时间。undefined
