繁体   English   中英

计算 Python / Cython / Numpy 中 2 个二进制向量之间的汉明距离的最快方法

[英]Fastest way to calculate the Hamming distance between 2 binary vectors in Python / Cython / Numpy

我正在尝试计算二进制向量和二进制向量矩阵之间的汉明距离。 我能找到的最快方法是使用带有 Numpy 的无符号 8 位整数:

import numpy as np
np.count_nonzero(data[0] !=  data, axis=1)

但是,这种方法的问题在于它首先找到所有不同的位,然后对差异的数量求和。 这不是有点浪费吗? 我尝试在 C++ 中实现一个基本版本,其中我还计算了不同的位数,因此最后不需要总和,但这要慢得多。 可能是因为 Numpy 使用 SIMD 指令。

所以我的问题是。 有没有办法使用 Numpy / Python / Cython 中的 SIMD 指令直接计算汉明距离?

理想情况下,您实际上希望 CPU 做的是sum += popcount( a[i] ^ b[i])和尽可能大的块。 例如,在 x86 上,使用 AVX2 对一条指令一次异或 32 个字节,然后再使用几条指令(包括 vpshufb 和 vpaddq)将计数累加到每个元素计数的 SIMD 向量中(最后水平求和)。

使用特定 ISA(如 x86-64)的 C++ 内在函数,这很容易。

您可以使用std::bitset<64>对 64 位块进行异或运算,并将.count()作为可移植的 API 来实现有效的 popcount。 Clang 可以将标量 popcount 自动矢量化为 AVX2,但 GCC 不能。

为了在不违反严格混叠的情况下安全地构造它,您可能需要将另一种类型的任意数据memcpy转换为unsigned long long


我不知道 Numpy 是否有一个用于编译的循环,否则你可能需要在一个通道中进行异或,然后在另一个通道中进行 popcount,这会降低计算强度,所以你肯定想将它缓存块成小块在您返回重新读取它们之前,它们会在 L1d 缓存中保持热状态。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM