Задача проста: написать сборку, которая вычисляет порядок целого числа, используя как можно меньше тактов.
- Порядок величины определяется как
log10
, нетlog2
. - Диапазон допустимых значений:
0
до , включительно. Поведение для ввода за пределами этого диапазона не определено.1012
- Значения должны быть округлены до ближайшего целого, за исключением того, что при заданном входном значении
0
выходные данные должны быть0
. (Вы можете считать это лучшим представлением отрицательной бесконечности, которое возможно в целых числах без знака). - Должна быть сборка х86.
- Целое число должно быть во время выполнения значения, а не статическое / инлайн целого числа. Поэтому мы не знаем, что это во время компиляции.
- Предположим, что у вас уже есть целое число, загруженное в регистр. (Но для ясности включите установку значения в регистр в ответ).
- Невозможно вызвать какие-либо внешние библиотеки или функции.
- Бесплатно использовать любые доступные инструкции в документации Intel .
- Нет C.
- Любая из ~ 7 архитектур Intel Core является приемлемой (перечислены на стр. 10 ). В идеале Nehalem (Intel Core i7).
Победившим ответом является тот, который использует наименьшее возможное количество тактов. То есть он может иметь наибольшее количество операций в секунду. С краткими сведениями о цикле часов можно ознакомиться здесь: http://www.agner.org/optimize/instruction_tables.pdf . Расчет тактов может произойти после публикации ответа.
math
fastest-algorithm
assembly
Лэнс Поллард
источник
источник
Ответы:
7 циклов, постоянное время
Вот решение, основанное на моем ответе на этот вопрос . Он использует BSR для подсчета количества битов, необходимых для хранения числа. Он ищет, сколько десятичных цифр необходимо для представления наибольшего числа, которое может содержать много битов. Затем он вычитает 1, если фактическое число меньше ближайшей степени 10 с таким количеством цифр.
Компилируется в GCC 4.6.3 для Ubuntu и возвращает значение в коде выхода.
Я не уверен, что интерпретирую эту таблицу циклов для любого современного процессора, но, используя метод @ DigitalTrauma на процессоре Nehalim, я получаю 7 ?
источник
The integer must be a runtime value, not a static/inline integer. So we don't know what it is at compile time.
Наилучший случай 8 циклов, наихудший случай 12 циклов
Поскольку это не ясно в вопросе, я основываю это на задержках Ivy Bridge.
Подход здесь состоит в том, чтобы использовать
bsr
(обратное сканирование битов) инструкцию как log2 () бедного человека. Результат используется в качестве индекса в таблице переходов, которая содержит записи для битов от 0 до 42. Я предполагаю, что, учитывая, что операция с 64-битными данными неявно требуется, тогда использованиеbsr
инструкции в порядке.В лучшем случае входные данные с помощью таблицы переходов могут отображать
bsr
результат непосредственно на величину. Например, для входных данных в диапазоне 32-63,bsr
результат будет 5, который отображается на величину 1. В этом случае путь инструкции:В наихудших входных данных
bsr
результат будет отображаться с двумя возможными значениями, поэтому элемент с перемычкой делает еще одну дополнительнуюcmp
проверку , чтобы определить, является ли входное значение> 10 n . Например, для входов в диапазоне 64-127bsr
результат будет 6. Соответствующая запись с перемычкой затем проверяет, является ли вход> 100, и соответственно устанавливает величину выхода.В дополнение к пути наихудшего случая у нас есть дополнительная инструкция mov для загрузки непосредственного 64-битного значения для использования в
cmp
, так что путь инструкции наихудшего случая:Вот код:
В основном это было сгенерировано из вывода ассемблера gcc для написанного мной кода на языке C для проверки концепции . Обратите внимание, что код C использует вычислимое goto для реализации таблицы переходов. Он также использует
__builtin_clzll()
встроенный gcc, который компилируется вbsr
инструкцию (плюс anxor
).Я рассмотрел несколько решений, прежде чем прийти к этому:
FYL2X
рассчитать натуральный логарифм, затемFMUL
по необходимой константе. Это, вероятно, выиграло бы это, если бы это был конкурс [tag: инструкция: гольф]. НоFYL2X
имеет время ожидания 90-106 для Ivy Bridge.Жестко закодированный бинарный поиск. Это на самом деле может быть конкурентоспособным - я оставлю это кому-то другому для реализации :).
Полная таблица результатов поиска. Это, я уверен, теоретически самый быстрый, но потребует таблицы поиска в 1 ТБ - пока не практично - возможно, через несколько лет, если закон Мура будет продолжать действовать.
источник
jmp
иjcc
не имеют задержки, только затраты на пропускную способность. Предсказание ветвлений + спекулятивное выполнение означают, что управляющие зависимости не являются частью цепочек зависимостей данных.