ОБНОВЛЕНИЕ: Этот ответ был изменен, чтобы мои комментарии соответствовали приведенному ниже исходному коду.
Существует возможность оптимизации, если у вас есть возможность использовать инструкции SSE2 и popcnt.
16 байт хорошо вписываются в регистр SSE. Используя c ++ и assembly / intrinsics, загрузите два 16-байтовых массива в регистры xmm и cmp их. Это создает битовую маску, представляющую истинное / ложное условие сравнения. Затем вы используете инструкцию movmsk для загрузки битового представления битовой маски в регистр x86; тогда это становится битовым полем, где вы можете сосчитать все 1, чтобы определить, сколько истинных значений у вас было. Аппаратная команда popcnt может быть быстрым способом подсчета всех единиц в регистре.
Для этого требуется знание ассемблера / встроенных функций и, в частности, SSE. Вы должны быть в состоянии найти веб-ресурсы для обоих.
Если вы запускаете этот код на машине, которая не поддерживает SSE2 или popcnt, вы должны затем выполнить итерацию по массивам и подсчитать различия с помощью подхода с развернутым циклом.
Удачи
Edit:
Поскольку вы указали, что не знаете сборки, вот пример кода, иллюстрирующий мой ответ:
#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 и команду popcnt, введенную в процессоре Phenom (это машина, которую я использую). Я считаю, что самые последние процессоры Intel с SSE4 также имеют popcnt. Эта функция не проверяет поддержку команд с CPUID; функция не определена, если используется на процессоре, который не имеет SSE2 или popcnt (вы, вероятно, получите недопустимую инструкцию для кода операции). Этот код обнаружения является отдельным потоком.
Я не рассчитал этот код; причина, по которой я думаю, это быстрее, потому что он сравнивает 16 байтов за раз, без ветвления. Вы должны изменить это, чтобы соответствовать вашей среде, и время самостоятельно, чтобы увидеть, работает ли это для вас. Я написал и проверил это на VS2008 SP1.
SSE предпочитает данные, которые выровнены по естественной 16-байтовой границе; если вы можете гарантировать это, то получите дополнительные улучшения скорости и можете изменить инструкции _mm_loadu_si128 на _mm_load_si128, что требует выравнивания.