#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.