Мне нужен быстрый целочисленный квадратный корень, который не требует явного деления. Целевая RISC-архитектура может выполнять операции, такие как add
, mul
, sub
, shift
за один цикл (ну, на самом деле результат операции записывается в третьем цикле, но с чередованием), поэтому любой алгоритм Integer, который использует эти операции и является быстрым, будет очень ценится
Это то, что у меня есть сейчас, и я думаю, что бинарный поиск должен быть быстрее, поскольку следующий цикл выполняется 16 раз каждый раз (независимо от значения). Я еще не отлаживал (пока), но, возможно, скоро выйду из него:
unsigned short int int_sqrt32(unsigned int x)
{
unsigned short int res=0;
unsigned short int add= 0x8000;
int i;
for(i=0;i<16;i++)
{
unsigned short int temp=res | add;
unsigned int g2=temp*temp;
if (x>=g2)
{
res=temp;
}
add>>=1;
}
return res;
}
Похоже, что текущая стоимость производительности вышеупомянутого [в контексте целевого RISC] представляет собой цикл из 5 инструкций (бит, набор, сравнение, сохранение, сдвиг). Вероятно, в кеше нет места для полной развертки (но это будет основной кандидат на частичную развертку (например, цикл из 4, а не 16), конечно). Таким образом, стоимость составляет 16 * 5 = 80 инструкций (плюс накладные расходы цикла, если не развернуты). Который, в случае полного чередования, будет стоить всего 80 (+2 для последней инструкции) циклов.
Могу ли я получить какую-то другую реализацию sqrt (используя только add, mul, bitshift, store/cmp) за 82 цикла?
ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ:
-
Почему вы не полагаетесь на компилятор для создания хорошего быстрого кода?
Для платформы не существует работающего компилятора C → RISC. Я буду переносить текущий эталонный код C в рукописный RISC ASM.
-
Вы профилировали код, чтобы увидеть, является ли
sqrt
узким местом?Нет, в этом нет необходимости. Целевая микросхема RISC составляет около двадцати МГц, поэтому учитывается каждая отдельная команда. Цикл ядра (вычисление коэффициента передачи энергии между патчем стрелка и приемника), где используется этот
sqrt
, будет выполняться ~ 1000 раз за каждый кадр рендеринга (конечно, при условии, что он будет достаточно быстрым), до 60000 в секунду и примерно 1 000 000 раз за всю демонстрацию. -
Вы пытались оптимизировать алгоритм, чтобы, возможно, удалить
sqrt
?Да, я уже сделал это. На самом деле я уже избавился от 2-х
sqrt
и множества делений (снято или заменено на сдвиг). Я вижу огромный прирост производительности (по сравнению с эталонной поплавковой версией) даже на моем гигагерцовом ноутбуке. -
Какое приложение?
Это рендерер в режиме реального времени с прогрессивной уточнением для compo demo. Идея состоит в том, чтобы иметь один цикл съемки на каждый кадр, чтобы он визуально сходился и выглядел лучше с каждым визуализированным кадром (например, до 60 раз в секунду, хотя растеризатор SW, вероятно, не будет таким быстрым [но, по крайней мере, он может работать на другом чипе параллельно с RISC - поэтому, если для рендеринга сцены требуется 2-3 кадра, RISC будет работать через 2-3 кадра данных радиации параллельно]).
-
Почему вы не работаете непосредственно в целевой ASM?
Потому что radiosity - это слегка задействованный алгоритм, и мне нужна возможность немедленного редактирования и продолжения отладки в Visual Studio. То, что я сделал на выходных в VS (пара сотен изменений кода для преобразования математики с плавающей запятой в целочисленные), заняло бы у меня 6 месяцев на целевой платформе только с отладкой печати ".
-
Почему вы не можете использовать разделение?
Потому что он в 16 раз медленнее на целевом RISC, чем любой из следующих: mul, add, sub, shift, сравнение, загрузка/сохранение (что занимает всего 1 цикл). Таким образом, он используется только в случае крайней необходимости (пару раз, к сожалению, когда переключение не может быть использовано).
-
Вы можете использовать справочные таблицы?
Движку уже нужны другие LUT, и копирование из основной оперативной памяти в небольшой кэш RISC непомерно дорого (и определенно не каждый кадр). Но, возможно, я мог бы сэкономить 128-256 байт, если бы это дало мне как минимум 100-200% прирост для
sqrt
. -
Каков диапазон значений для
sqrt
?Мне удалось уменьшить его до простого беззнакового 32-битного целого (4 294 967 295)