Pull to refresh

Comments 10

Судя по документации третий цикл заменяется на: length += res;
Также не совсем понятно зачем первый цикл — можно прочитать без выравнивания с помощью _mm_loadu_si128 и сделать то же, что в основном цикле.
Еще стоит попробовать заменить _mm_cmpistri на _mm_cmpestri — может, станет быстрее.
когда loadu попадает на границу страницы, это в лучшем случае медленно, в худшем — segfault.
Ладно, можно прочитать по выровненному вниз адресу, и проверить как в статье про «самый быстрый» strlen, правильно сдвинув результат movemask-а.
есть у меня подозрение, что выфильтровывание нулей перед невыровненным участком того не стоит для коротких строк
Интринсики
__m128i data = _mm_load_si128((__m128i*)(str + length));
if ((res = _mm_cmpistri(z128, data, _SIDD_CMP_EQUAL_EACH)) != 16)

Компилируются в одну инструкцию
pcmpistri   xmm1,xmmword ptr [eax+edx],8

Замена на _mm_cmpestri делает код медленнее, почти в 2 раза.
Выровненная память быстрее на 2-3%, исключения misaligned нет, и да видимо выровнить предварительно лучше, что бы не боятся в основном цикле выхода за границу страницы.
На счет _mm_cmpestri — странно. Но все равно спасибо за тесты.
Сделали ли мы самую быструю strlen? – К сожалению, нет, ребята с www.strchr.com/sse2_optimised_strlen сделали еще быстрее и не используя SSE4.2.

А за счет чего, если не секрет? Вроде как по latency/throughput pcmpstri обходит pcmpeqb + pmovmskb + not + bsf для всех актуальных процов. Или они сами итерации грамотнее реализовали?
А пробовали ли вы x64 вместо устаревшего x86?
У меня 17я студия, ваш бенч показывает такое:
x86 debug — 8.5
x86 release (все оптимизации) — 3.1
x64 debug — 6.77
x64 release (все оптимизации) — 1.7
То есть x86 и x64 довольно по-разному себя ведут.
Добавил тесты для x64. Поведение компилятора VS аналогично.
Sign up to leave a comment.

Articles