我在我的应用程序中使用 KNN 搜索。大数组会消耗大量内存,我正在尝试减小数组的大小。
在不影响结果的情况下减少维度对我来说太难了。因此,我希望通过使用较小的 dtype
来减小大小:
In [46]: features = np.random.random((500000, 128)).astype('float32')
In [47]: smaller = features.astype('float16')
In [48]: nbrs = NearestNeighbors(n_neighbors=20, algorithm='brute', metric='l2').fit(f
...: eatures)
In [49]: smaller_nbrs = NearestNeighbors(n_neighbors=20, algorithm='brute', metric='l2
...: ').fit(smaller)
In [50]: %timeit nbrs.kneighbors(features[3:4])
10 loops, best of 3: 61.7 ms per loop
In [51]: %timeit smaller_nbrs.kneighbors(smaller[3:4])
1 loop, best of 3: 526 ms per loop
如您所见,切换到 float16
会使 kneighbors
调用速度变慢约 10 倍。
为什么会出现这样的情况呢?我可以做些什么来让它运行得像使用 float32 时一样快吗?
最佳答案
32b 浮点比 16b 浮点工作得更快的原因是大多数现代 CPU 本身支持 32b 浮点,而 16b 浮点可能需要一些特殊处理(例如转换为 float32)。因此,当您节省 RAM 时,您在计算上的花费就会显着增加。 当使用正确的 CPU 指令时,这种情况可以得到缓解,但这里的情况可能并非如此(Intel 在 2012 年引入了特殊的半精度操作码;see)。需要注意的是,只有当您的数组大于 256K(这显然是您的情况)时,您才能实现任何明显的加速,但改进在 20% 到 40% 之间,这很容易因数组的非最佳遍历而丢失(缓存未命中)。
此外,另一个需要考虑的因素是内存数据对齐,通常在使用完整字时效果更好(对于许多 CPU:32b 或 64b)。有关内存对齐和缓存使用的影响的大量详细信息,您可以在 Scott Myers' presentation 中找到。 .
关于python - 当我使用较小的 float 时,为什么 sklearn 中的 KNN 实现速度会变慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44065954/