更新:此答案已被修改,以使我的评论与下面提供的源代码相匹配。
如果您能够使用 SSE2 和 popcnt 指令,则可以进行优化。
16 个字节恰好适合 SSE 寄存器。使用 c++ 和汇编/内在函数,将两个 16 字节数组加载到 xmm 寄存器中,然后对它们进行 cmp。这会生成一个位掩码,表示比较的真/假条件。然后,您使用 movmsk 指令将位掩码的位表示加载到 x86 寄存器中;然后这成为一个位字段,您可以在其中计算所有 1 以确定您有多少真实值。硬件 popcnt 指令可以是一种快速计算寄存器中所有 1 的方法。
这需要了解汇编/内在知识,尤其是 SSE。您应该能够找到两者的网络资源。
如果您在不支持 SSE2 或 popcnt 的机器上运行此代码,则必须遍历数组并使用展开循环方法计算差异。
祝你好运
编辑:由于您表示您不知道汇编,这里有一些示例代码来说明我的答案:
#include "stdafx.h"
#include <iostream>
#include "intrin.h"
inline unsigned cmpArray16( char (&arr1)[16], char (&arr2)[16] )
{
__m128i first = _mm_loadu_si128( reinterpret_cast<__m128i*>( &arr1 ) );
__m128i second = _mm_loadu_si128( reinterpret_cast<__m128i*>( &arr2 ) );
return _mm_movemask_epi8( _mm_cmpeq_epi8( first, second ) );
}
int _tmain( int argc, _TCHAR* argv[] )
{
unsigned count = 0;
char arr1[16] = { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 };
char arr2[16] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 };
count = __popcnt( cmpArray16( arr1, arr2 ) );
std::cout << "The number of equivalent bytes = " << count << std::endl;
return 0;
}
一些注意事项:此函数使用 SSE2 指令和在 Phenom 处理器(我使用的机器)中引入的 popcnt 指令。我相信最新的带有 SSE4 的英特尔处理器也有 popcnt。此函数不检查 CPUID 的指令支持;如果在没有 SSE2 或 popcnt 的处理器上使用该函数是未定义的(您可能会得到一个无效的操作码指令)。该检测代码是一个单独的线程。
我没有对这段代码计时;我认为它更快的原因是因为它一次比较 16 个字节,无分支。你应该修改它以适应你的环境,并自己计时,看看它是否适合你。我在 VS2008 SP1 上编写并测试了这个。
SSE 更喜欢在自然 16 字节边界上对齐的数据;如果你能保证那么你应该得到额外的速度改进,你可以将_mm_loadu_si128指令更改为_mm_load_si128,这需要对齐。