Здравствуйте, AleksandrN, Вы писали:
AN>А какой компилятор и какой код оптимизирует до POPCNT? Сделал подсчёт с помощью сдвигов и битовой маски, но gcc с опциями -O3 -msse4 просто развернул цикл, но POPCNT не использовал.
Компиляторозависимые интринсики надо использовать. Что-то вроде int __builtin_popcount. Ну или иметь в стандартной библиотеке такие функции и их оптимизировать при компиляции, такое видел в Rust и в Java. Ну или просто на язык ассемблера написать этот кусочек.
Кстати утяну с JDK реализацию с помощью битовой арифметики:
i = i - ((i >>> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
i = (i + (i >>> 4)) & 0x0f0f0f0f;
i = i + (i >>> 8);
i = i + (i >>> 16);
return i & 0x3f;
Это для 32-битов. Фиг его знает, как оно работает, но, по идее, если не использовать отдельные инструкции процессора, то такой код будет крайне быстр, т.к. это просто последовательность быстрых операций без ветвлений, обращений к памяти и прочей гадости, вжух по регистрам и всё.