Это известно как' Вес Hamming ', 'popcount' или 'поперечное дополнение'.
'лучший' алгоритм действительно зависит, на котором ЦП Вы идете и каков Ваш шаблон использования.
Некоторые центральные процессоры имеют единственную встроенную инструкцию сделать, она и другие имеет параллельные инструкции, которые действуют на битовый векторы. Параллельные инструкции (как x86 popcnt
, на центральных процессорах, где это поддерживается) почти наверняка будут самыми быстрыми. Некоторой другой архитектуре можно было реализовать медленную инструкцию с микрокодированным циклом, который тестирует немного на цикл ( необходима цитата ).
предварительно заполненный метод поиска по таблице А может быть очень быстрым, если Ваш ЦП имеет большой кэш, и/или Вы делаете много этих инструкций в жестком цикле. Однако это может пострадать из-за расхода 'неудачного обращения в кэш', где ЦП должен выбрать часть таблицы от оперативной памяти.
, Если Вы знаете, что Ваши байты будут главным образом 0 или главным образом 1's тогда, существуют очень эффективные алгоритмы для этих сценариев.
я полагаю, что очень хороший алгоритм общего назначения следующий, известен как 'параллель' или 'переменная точность алгоритм SWAR'. Я выразил это на подобном C псевдо языке, Вы, возможно, должны скорректировать его для работы на конкретный язык (например, использующий uint32_t для C++ и>>> в Java):
int numberOfSetBits(int i)
{
// Java: use >>> instead of >>
// C or C++: use uint32_t
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
Это имеет лучшее поведение худшего случая любого из обсужденных алгоритмов, так будет эффективно иметь дело с любым шаблоном использования или оценивает Вас бросок в него.
Этот поразрядный-SWAR алгоритм мог параллелизировать, чтобы быть сделанным в нескольких векторных элементах сразу, вместо в единственном целочисленном регистре, для ускорения на центральных процессорах с SIMD, но никакой применимой popcount инструкцией. (например, код x86-64, который должен работать на любом ЦП, не просто Nehalem или позже.)
Однако лучший способ использовать векторные инструкции для popcount обычно при помощи переменной перестановки, чтобы сделать поиск по таблице для 4 битов во время каждого байта параллельно. (4 бита индексируют 16 таблиц записи, сохраненных в векторном регистре).
На Intel CPUs, аппаратные средства 64 бита popcnt инструкция могут превзойти по характеристикам реализация разрядной параллели SSSE3 PSHUFB
приблизительно фактором 2, но [только 115], если Ваш компилятор получает его просто право . Иначе SSE может выйти значительно вперед. Более новые версии компилятора знают popcnt ложная зависимость проблема на Intel.
Ссылки:
https://graphics.stanford.edu/~seander/bithacks.html
https://en.wikipedia.org/wiki/Hamming_weight
http://gurmeet.net/puzzles/fast-bit-counting-routines/
http://aggregate.ee.engr.uky.edu/MAGIC/#Population%20Count%20 (Ones%20Count)
Загрузите, запишите и установите Lubuntu от альтернативного диска установки. Вы найдете всю информацию необходимой здесь: https://help.ubuntu.com/community/Lubuntu/Alternate_ISO