Проблема, естественно, в O (n), в результате ваше решение, вероятно, наиболее эффективно.
Поскольку вы пытаетесь подсчитать произвольное подмножество битов, вы не можете подсчитать биты, когда они установлены (будет обеспечивать повышение скорости, если вы не будете устанавливать биты слишком часто).
Вы можете проверить, есть ли у процессора, который вы используете, команда, которая будет возвращать количество установленных бит.Например, процессор с SSE4 может использовать POPCNT в соответствии с этим постом .Это, вероятно, не будет работать для вас, так как .Net не позволяет сборку (потому что она не зависит от платформы).Кроме того, процессоры ARM, вероятно, не имеют эквивалента.
Вероятно, лучшим решением будет поиск таблицы (или переключение, если вы можете гарантировать, что переключатель будет скомпилирован в один переход к currentLocation + byteValue).Это даст вам счет для всего байта.Конечно, BitArray не предоставляет доступ к базовому типу данных, поэтому вам придется создать свой собственный BitArray.Вы также должны были бы гарантировать, что все биты в байте всегда будут частью пересечения, что маловероятно.
Другим вариантом будет использование массива логических значений вместо BitArray.Это имеет то преимущество, что нет необходимости извлекать бит из других в байте.Недостатком является то, что массив будет занимать в 8 раз больше места в памяти, что означает не только потраченное впустую пространство, но и больший объем данных при выполнении итерации по массиву для выполнения подсчета.
Разница между поиском стандартного массиваи поиск BitArray выглядит следующим образом:
Array:
- offset = index * indexSize
- Получить память в местоположении + смещение и сохранить в значение
BitArray:
- index = index / indexSize
- offset = index * indexSize
- Получить память в местоположении + смещение и сохранить в значение
- position = index% indexSize
- Бит позиции значения сдвига
- value = значение и 1
За исключением № 2 для массивов и № 3 для большинстваэти команды занимают 1 процессорный цикл для завершения.Некоторые команды могут быть объединены в 1 команду с использованием процессоров x86 / x64, хотя, вероятно, не с ARM, поскольку она использует сокращенный набор инструкций.
Какая из двух (массив или BitArray) работает лучше, будет зависеть от вашей платформы(скорость процессора, инструкции процессора, размеры кэш-памяти процессора, скорость кэш-памяти процессора, объем системной памяти (Ram), скорость системной памяти (CAS), скорость соединения между процессором и RAM), а также разброс индексов, которые вы хотите посчитать(перекрестки чаще всего кластеризованы или они распределены случайным образом).
Подводя итог: вы, вероятно, могли бы найти способ сделать это быстрее, но ваше решение является самым быстрым для васваш набор данных, используя битовую булеву модель в .NET.
Редактировать: , убедитесь, что вы получаете доступ к индексам, которые вы хотите посчитать по порядку.Если вы обращаетесь к индексам 200, 5, 150, 151, 311, 6 в указанном порядке, то вы увеличиваете количество кеш-пропусков, что приводит к увеличению времени ожидания получения значений из ОЗУ.