Есть ли какая-либо разница в эффективности подсчета начальных / конечных единиц / нулей?

#rust #arm #bit-manipulation #x86-64 #varint

# #Ржавчина #arm #манипулирование битами #x86-64 #varint

Вопрос:

Я разрабатываю целое число переменной длины с префиксом.

У Rust есть методы для подсчета начальных и конечных единиц и нулей: https://doc.rust-lang.org/std/primitive.u64.html#method .leading_zeros

Есть ли какая-либо разница в эффективности этих методов на x86_64, arm32 и arm64?

например, если подсчет конечных единиц выполняется быстрее, чем конечные нули, я буду использовать xxxx0111 вместо xxxx1000 для байта кодирования длины (для трех следующих байтов, в этом примере).

Комментарии:

1. on x86_64, arm32 and arm64? Итак, какие наборы инструкций поддерживаются? Лучшим и самым простым способом было бы просто написать небольшую программу и проверить сгенерированную сборку на этих архитектурах. Пожалуйста, попробуйте. Помните о правилах оптимизации .

Ответ №1:

Подсчет завершающих нулей выполняется быстрее, чем завершающих единиц во всех 3 ISA: x86 *, ARM, AArch64. Все они предоставляют инструкции по подсчету нулей, такие как x86 bsf (найти младший установленный бит) или x86 BMI1 tzcnt (завершающий нулевой счет). Подсчет начальных / конечных единиц в переменной времени выполнения потребует отрицания входных данных.

ARM / AArch64 обеспечивает подсчет начальных нулей, но лучшим вариантом для конечного нуля является rbit / clz с обратным битом (начиная с ARMv6T2 или ARMv7). https://godbolt.org/z/Yr7eac . Перед этим компиляторы должны изолировать младший установленный бит x amp; -x , подсчитать начальные нули этого и принять 31-clz(xamp;-x) .


(На x86 подсчет начальных нулей наиболее эффективен с BMI1. Без этого bsr может дать вам позицию самого высокого установленного бита, поэтому компилятору необходимо 31-bsr(x) реализовать clz. На процессорах AMD bsf / bsr работают значительно медленнее, чем их аналоги tzcnt / lzcnt, поэтому, если возможно, рекомендуется скомпилировать с -march=native помощью или любого другого эквивалента Rust.)

Комментарии:

1. Спасибо, я раньше не сталкивался с godbolt.

2. rbit доступно с armv7

3. @JakeAlquimista’Lee: В моей ссылке Godbolt показано, что GCC использует rbit with -march=armv6t2 . О, но, видимо, не с обычным ARMv6.