Более быстрое целочисленное деление, когда знаменатель известен?

Я работаю над устройством GPU, которое имеет очень высокую целочисленную задержку деления, несколько сотен циклов. Я ищу оптимизацию подразделений.

все деления по знаменателю, который находится в наборе { 1,3,6,10 }, однако числитель является положительным значением времени выполнения, примерно 32000 или меньше. из-за ограничений памяти таблица поиска может быть не очень хорошим вариантом.

можете ли вы придумать альтернативы? Я думал о вычислении инверсий с плавающей точкой и использовании их для умножения числитель.

спасибо

PS. спасибо люди. бит shift hack это действительно круто. для восстановления после roundoff я использую следующий сегмент C:

// q = m/n
q += (n*(j +1)-1) < m;

3 ответов


a/b=a*(1/b)
x=(1<<16)/b
a/b=(a*x)>>16

можете ли вы построить таблицу поиска для знаменателей? поскольку вы сказали 15-битные числители, вы можете использовать 17 для сдвигов, если все без знака 32 бит:

a/b=a*((1<<17)/b)>>17

чем больше сдвиг, тем меньше ошибка округления. Вы можете сделать проверку грубой силы, чтобы увидеть, сколько раз, если таковые имеются, это на самом деле неправильно.


стандартные встроенные системы взломать для этого, чтобы преобразовать целочисленное деление на N в умножение с фиксированной точкой на 1 / N.

предполагая 16 бит, 0.33333 может быть представлен как 21845 (десятичный). Умножьте, давая 32-разрядное целое произведение, и сдвиньте вниз 16 бит.

вы почти наверняка столкнетесь с некоторой ошибкой округления (усечения). Это может быть или не быть чем-то, с чем вы можете жить.

возможно, стоит посмотреть на ваш GPU и увидеть если вы можете вручную кодировать более быструю процедуру целочисленного деления, используя свои знания ограниченного диапазона числителя.


книги "восторг хакера" Генри Уоррена, имеет целую главу, посвященную целочисленному делению на константы, включая методы, которые преобразуют целочисленное деление в серию операций умножения / сдвига/добавления.

эта страница вычисляет магические числа для операций умножения / сдвига / добавления: