MacOS下faiss.reconstruct_n()生成numpy数组引发系统错误求助
问题详情
使用faiss.reconstruct_n()重建索引向量后,尝试用该数组训练Kmeans索引时触发段错误,错误码为exit code 139(interrupted by signal 11: SIGSEGV)。怀疑与MacOS和其他系统的float类型字节大小差异有关,寻求解决方法。
复现代码
import faiss import numpy as np d = 768 ncentroids = 15 niter = 2 faiss_index = faiss.IndexFlatL2(d) x0 = np.random.random( (5000, d) ) faiss_index.add(x0) x = faiss_index.reconstruct_n() kmeans_index = faiss.Kmeans(d, ncentroids, niter=niter, verbose=True) kmeans_index.train(x)
错误信息
Sampling a subset of 3840 / 5000 for training Clustering 3840 points
in 768D to 15 clusters, redo 1 times, 2 iterations Preprocessing in
0.01 sProcess finished with exit code 139 (interrupted by signal 11: SIGSEGV)
平台配置
- faiss-cpu == 1.8.0
- Python 3.11.6 on darwin(Clang 13.0.0)
- 设备:MacBook Pro(Mac14,9,MPHE3LL/A)
- 芯片:Apple M2 Pro
- 内存:16 GB
解决方法
核心原因是faiss默认使用float32存储向量,但numpy.random.random生成的是float64数组,reconstruct_n()返回的也是float64,而faiss 1.8.0在Apple Silicon芯片上对float64的Kmeans训练存在兼容性问题,导致段错误。以下是具体修复方案:
方案1:统一使用float32类型
确保所有输入faiss的向量、重建后的向量均为float32类型:
import faiss import numpy as np d = 768 ncentroids = 15 niter = 2 faiss_index = faiss.IndexFlatL2(d) # 生成float32类型的初始向量,匹配faiss默认存储格式 x0 = np.random.random((5000, d)).astype(np.float32) faiss_index.add(x0) # 重建后显式转换为float32(避免隐式类型不匹配) x = faiss_index.reconstruct_n().astype(np.float32) kmeans_index = faiss.Kmeans(d, ncentroids, niter=niter, verbose=True) kmeans_index.train(x)
方案2:使用reconstruct_n_into()直接写入预分配的float32数组
提前创建float32数组,用reconstruct_n_into()直接写入,减少类型转换开销:
import faiss import numpy as np d = 768 ncentroids = 15 niter = 2 faiss_index = faiss.IndexFlatL2(d) x0 = np.random.random((5000, d)).astype(np.float32) faiss_index.add(x0) # 预分配float32数组,直接写入重建结果 x = np.empty((faiss_index.ntotal, d), dtype=np.float32) faiss_index.reconstruct_n_into(0, faiss_index.ntotal, x) kmeans_index = faiss.Kmeans(d, ncentroids, niter=niter, verbose=True) kmeans_index.train(x)
方案3:升级faiss版本
faiss 1.8.0在Apple Silicon上存在已知兼容性问题,升级到最新的faiss-cpu版本(如1.8.4及以上)可修复部分底层架构相关的bug:
pip install --upgrade faiss-cpu
内容的提问来源于stack exchange,提问作者Alexander Borochkin

