在多個GPU上運行Faiss以及性能測試
一、Faiss的基本使用
1.1在CPU上運行
Faiss的所有算法都是圍繞index展開的。不管運行搜索還是聚類,首先都要建立一個index。
import faiss # make faiss available index = faiss.IndexFlatL2(d) # build the index # d is the dimension of data
在運行上述代碼后,就可以添加數據並運行搜索了。
index.add(xb)
# xb is the base data D, I = index.search(xq, k) # xq is the query data # k is the num of neigbors you want to search # D is the distance matrix between xq and k neigbors # I is the index matrix of k neigbors
1.2在單個GPU上運行
在單個GPU上運行的語法基本與在GPU上運行類似。但是需要申明一個GPU資源的標識.
res = faiss.StandardGpuResources()
# we need only a StandardGpuResources per GPU flat_config = 0 # flat_config is an ID. if you have 3 GPUs, flat_configs maybe 0, 1, 2 index = faiss.GpuIndexFlatL2(res, d, flat_config) # build the index index.add(xb) D, I = index.search(xq, k)
1.3在多個GPU上運行
在多個GPU上運行時便有所不同, 我們需要將數據集分割給多個GPU以完成並行搜索。
在Faiss中提供了兩種方法實現:IndexProxy和IndexShards。
下面着重介紹IndexProxy。
res = [faiss.StandardGpuResources() for i in range(ngpu)] # first we get StandardGpuResources of each GPU # ngpu is the num of GPUs indexes = [faiss.GpuIndexFlatL2(res[i], i, d, useFloat16) for i in range(ngpu)] # then we make an Index array # useFloat16 is a boolean value index = faiss.IndexProxy() for sub_index in indexes: index.addIndex(sub_index) # build the index by IndexProxy
二、kmeans測試

1.jpg
如圖所示數據為1M個,中心點為1K個。
在不同數據維度以及GPU數目下迭代20次所需要的時間。
三、暴力搜索測試
數據集為sift1M, 該數據集共1M個,128維。(運行在兩個K40M GPU上)

2.jpg

3.jpg
可以看到在每次查詢10K個數據的1024個最近鄰居時平均每個查詢只需360ns。當需要查詢的鄰居數下降時,查詢時間能夠降至100ns。
四、IVFPQ搜索測試
數據集同上,運行環境同上。
基本參數:
numCentroids=4096
numQuantizers=64
首先我們測試nprob對性能的影響

4.jpg
當nprob上升時, 每次查詢時間會增加, 同時查詢的准確度也會上升。但上升到一定程度上升幅度便會迅速變小。我們取准確度的拐點值nprob=32進行下一步測試。
接下來我們測試查詢的鄰居數即k值對性能的影響。

5.jpg
可以看到查詢時間不再是線性增長了。也就意味着對於IVFPQ鄰居數不宜太多。
選定k=32進行下一步測試。

6.jpg
如圖所示,隨着每次查詢的數量上升,平均查詢時間先變小在變大,這可能是由於數據量小時開銷比較大導致平均查詢時間較大。可以看到隨着查詢的數量上升, 平均查詢時間上升但上升幅度放緩,估計會在250ns左右穩定。
作者:momo豬
鏈接:https://www.jianshu.com/p/4fb45b9070d1
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。