我正在Visual Studio 2010 C ++上实现
我有两个二进制数组。例如,
array1[100] = {1,0,1,0,0,1,1, .... }
array2[100] = {0,0,1,1,1,0,1, .... }
要计算array1
和array2
之间的Hamming distance,
array3[100]
存储xor
和array1
的{{1}}结果。
然后我必须计算array2
中1
位的数量。为此,我知道我可以使用array3
指令。
现在,我正在做类似下面的事情:
__popcnt
它显示了良好的结果,但速度很慢。我怎样才能让它更快?
答案 0 :(得分:3)
array3
似乎有点浪费,你正在访问一个你不需要的额外400字节的内存。我会尝试比较你的以下内容:
for (int i = 0; i < 100; ++i) {
result += (array1[i] ^ array2[i]); // could also try != in place of ^
}
如果这有帮助,那么我将其作为练习留给读者如何应用此更改和 duskwuff's。
答案 1 :(得分:2)
实施后,__popcnt
电话无效。它实际上让你慢下来。
__popcnt
计算其参数中的设置位数。你只传递一个元素,看起来它保证为0或1,所以结果(也是0或1)没用。这样做会稍快一些:
popcnt_result += array3[i];
根据阵列的布局方式,您可能会或可能无法以更聪明的方式使用__popcnt
。具体来说,如果您的数组由一个字节的元素组成(例如char
,bool
,int8_t
或类似的元素),您可以一次对四个元素执行一次人口统计:< / p>
for(i = 0; i < 100; i += 4) {
uint32_t *p = (uint32_t *) &array3[i];
popcnt_result += __popcnt(*p);
}
(请注意,这取决于100可以被4整除的事实。否则你必须为最后几个元素添加一些特殊情况处理。)
如果数组包含较大的值,例如int
,那么你运气不好,而且仍然无法保证这比上面的天真实现更快。
答案 2 :(得分:1)
如果您的数组只包含两个值(0
或1
),则汉明距离只是相应值不同的位置数。这可以使用标准库中的std::inner_product
一次完成。
#include <iostream>
#include <functional>
#include <numeric>
int main()
{
int array1[100] = { 1,0,1,0,0,1,1, ... };
int array2[100] = { 0,0,1,1,1,0,1, ... };
int distance = std::inner_product(array1, array1 + 100, array2, 0, std::plus<int>(), std::not_equal_to<int>());
std::cout << "distance=" << distance << '\n';
return 0;
}