Я пытаюсь сравнить две строки из pixel
s.Почему это медленнее, чем memcmp
A pixel
определяется как struct
, содержащий значения 4 float
(RGBA).
Причина, по которой я не использую memcmp
, состоит в том, что мне нужно вернуть положение 1-го другого пикселя, который memcmp
не делает.
Моя первая реализация использует SSE
встроенные функции, и ~ 30% медленнее, чем memcmp
:
inline int PixelMemCmp(const Pixel* a, const Pixel* b, int count)
{
for (int i = 0; i < count; i++)
{
__m128 x = _mm_load_ps((float*)(a + i));
__m128 y = _mm_load_ps((float*)(b + i));
__m128 cmp = _mm_cmpeq_ps(x, y);
if (_mm_movemask_ps(cmp) != 15) return i;
}
return -1;
}
Затем я обнаружил, что обработка значений в виде целых чисел вместо поплавков ускорили вещи немного, и теперь только ~ 20% медленнее, чем memcmp
.
inline int PixelMemCmp(const Pixel* a, const Pixel* b, int count)
{
for (int i = 0; i < count; i++)
{
__m128i x = _mm_load_si128((__m128i*)(a + i));
__m128i y = _mm_load_si128((__m128i*)(b + i));
__m128i cmp = _mm_cmpeq_epi32(x, y);
if (_mm_movemask_epi8(cmp) != 0xffff) return i;
}
return -1;
}
Из того, что я читал на другие вопросы, реализация МС memcmp
также осуществляется с использованием SSE
. Мой вопрос в том, что другие трюки в реализации MS имеют его рукав, который у меня нет? Как он все еще быстрее, хотя он побайтовое сравнение?
Является ли выравнивание проблемой? Если pixel
содержит 4 поплавки, не будет ли выделен массив пикселей уже на границе 16 байтов?
Я компилирую с помощью /o2
и всех флагов оптимизации.
Нет, нет гарантии, что он будет выровнен по 16 байт, если вы сами не позаботитесь о нем. – interjay
Да, выравнивание - проблема. Используемые вами варианты компиляции также актуальны. Вы также должны показать сгенерированный asm. Возможно, компилятору не хватает развертки цикла или какой-либо другой оптимизации вашего кода. –