Чому апаратне ділення займає набагато більше часу, ніж множення?


37

Чому апаратне ділення займає так багато часу, ніж множення на мікроконтролері? Наприклад, на dsPIC поділ займає 19 циклів, тоді як множення займає лише один тактовий цикл.

Я пройшов через деякі підручники, в тому числі алгоритм Дивізії і алгоритм множення на Вікіпедії. Ось мої міркування.

Алгоритм поділу, як метод повільного поділу з відновленням у Вікіпедії, є рекурсивним алгоритмом. Це означає, що (проміжні) результати від кроку kвикористовуються як вхід до кроку k+1, а це означає, що ці алгоритми не можуть бути паралельними. Таким чином, nдля завершення поділу потрібно щонайменше циклів, тоді nяк це кількість бітів у дивіденді. Для 16-бітових дивідендів це дорівнює щонайменше 16 циклів.

Алгоритм множення не повинен бути рекурсивним, а це означає, що можна паралелізувати його. Однак існує багато різних алгоритмів множення, і я не маю поняття, який з них може використовуватися мікроконтролерами. Як працює множення на апаратному / мікроконтролері?

Я знайшов алгоритм множника Dadda , який повинен завершити лише один тактовий цикл. Однак я не розумію, що алгоритм тата проходить у три етапи, тоді як результати кроку 1 використовуються на кроці 2 і т.д.


2
Алгоритм насправді не визначає кількість тактового циклу. У вашому конкретному процесорі може бути апаратний множник / дільник, який працює за один цикл або 20 циклів незалежно від внутрішньої реалізації.
Євген Ш.

1
ОП, чи можете ви надати посилання, яке дає більше інформації про цикли 19 проти 1, про які ви говорите? Щось конкретно у вашому DSP.
Володимир Крейвер

1
Дякуємо за відповіді. Ось таблиця для мого мікроконтролера: ww1.microchip.com/downloads/en/DeviceDoc/70005127c.pdf . Див. Огляд набору інструкцій, починаючи з сторінки 292. Там сказано, що всі інструкції DIV займають 18 циклів, а всі інструкції MUL займають лише 1 цикл. Але це не часто для цього MCU, я бачив це в багатьох інших MCU.
Марко Гулін

2
@Curd, ну вони приблизно однакові, чи не так. Для мене Я не думаю, що це так добре ілюструє.
TonyM

1
Інший фактор - економія та використання. Більшість звичаїв посилаються на множення набагато частіше, ніж на ділення. Виділення великої площі кремнію для швидшого функціонування апаратного поділу, яке буде використовуватися порівняно рідко, є поганою економією. Краще зробити менший і дешевший чіп, або використовувати додаткову логіку більш продуктивним чином. До речі, коли я починав із міні-комп'ютерів, розділення не завжди було інструкцією. На деяких машинах це був виклик бібліотеки програмного забезпечення, як квадратний корінь.
nigel222

Відповіді:


34

Роздільник відображає набагато менш елегантно типове обладнання. Візьмемо для прикладу решітки з гратами ICE40.

Порівняємо два випадки: це 8x8 біт на 16-бітний множник:

module multiply (clk, a, b, result);
   input clk;
   input [7:0]a;
   input [7:0]b;
   output [15:0]result;
   always @(posedge clk)
     result = a * b;
endmodule // multiply

і цей дільник, що зменшує 8 і 8 бітові операнди до 8 бітового результату:

module divide(clk, a, b, result);
   input clk;
   input [7:0] a;
   input [7:0] b;
   output [7:0] result;
   always @(posedge clk)
     result = a / b;
endmodule // divide

(Так, я знаю, годинник нічого не робить )

Огляд сформованої схеми при зіставленні множника на ICE40 FPGA можна знайти тут, а дільник тут .

Статистика синтезу від Йосіса:

примножувати

  • Кількість проводів: 155
  • Кількість дротів: 214
  • Кількість державних проводів: 4
  • Кількість біт загального доступу: 33
  • Кількість спогадів: 0
  • Кількість бітів пам'яті: 0
  • Кількість процесів: 0
  • Кількість комірок: 191
    • SB_CARRY 10
    • SB_DFF 16
    • SB_LUT4 165

ділити

  • Кількість проводів: 145
  • Кількість дротів: 320
  • Кількість державних проводів: 4
  • Кількість біт загального доступу: 25
  • Кількість спогадів: 0
  • Кількість бітів пам'яті: 0
  • Кількість процесів: 0
  • Кількість комірок: 219
    • SB_CARRY 85
    • SB_DFF 8
    • SB_LUT4 126

Варто зазначити, що розмір згенерованого verilog для помножувача на повну ширину і дільник, що має максимальний розмір, не такий екстремальний. Однак якщо ви подивитеся на малюнки нижче, ви помітите, що множник має глибину 15, тоді як дільник більше схожий на 50; критичний шлях (тобто найдовший шлях, який може виникнути під час роботи) - це те, що визначає швидкість!


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

Помножте

Помножте на ICE40 (попередження: ~ 100 Мп пікселів )

Масштабоване зображення множника

Розділити

( Розділити на ICE40 ) (попередження: ~ 100 Мп пікселів )

Масштабоване зображення дільника


4
ні, ви можете їх реалізувати без ітерації. Але це просто пройде досить тривалий час, поки дійсний результат "просмикнеться" за логікою. Наведені вище варіанти не є ітераційними.
Маркус Мюллер

9
Я хочу настінний плакат дільника.
Ян Хоусон

5
Зараз у документі множення є PDF . Це 3378 × 3177 мм, тому, будь ласка, обговоріть зі своїм важливим іншим, перш ніж ставити це на стелю спальні.
Маркус Мюллер

2
Ваші 100-мегапіксельні зображення є вражаючими, але є надмірними для точки, яку ви намагаєтеся зробити, і вони створюють величезні проблеми для тих, хто намагається переглянути цю сторінку на пристрої з обмеженою пам’яттю, наприклад телефоні чи планшеті. Якщо ви хочете відобразити зображення вбудованим, знайдіть спосіб попереднього перегляду з меншою роздільною здатністю.
Трейд Дейва

4
Йо, ці графіки графіків зняті з гачка, йо!
Спенсер Вільямс

8

Повільне ділення за своєю суттю є ітераційним, тому воно, як правило, займає більше часу. Існують дещо швидші алгоритми повільного поділу, ніж прості, за допомогою таблиць пошуку. Алгоритм SRT виробляє два біти за цикл. Помилка в такій таблиці стала причиною сумнозвісної помилки Pentium FDIV (бл. 1994). Потім існують так звані алгоритми швидкого поділу.

Звичайно, в принципі, ви можете просто використовувати величезну таблицю пошуку, щоб обчислити добуток або коефіцієнт двох чисел і, таким чином, отримати результати за один цикл, але це, як правило, швидко стає непрактичним, оскільки кількість бітів на число збільшується.


Але суть полягає в тому, що алгоритми ділення не можуть бути паралельними, на відміну від алгоритмів множення, і тому вони настільки повільніші?
Марко Гулін

2
@MarkoGulin "не може" - дуже сильне твердження. Це, звичайно, не просто.
Spehro Pefhany

2
Я думаю, ви могли б послабити це від "алгоритми поділу не можна паралелізувати" до "способи, які ми знайшли для паралелізації поділу, більше напружують апаратне забезпечення, що реалізує поділ, ніж паралелізоване множення". Sphero наводить приклад того, як зробити поділ на один цикл, використовуючи ворота O (2 ^ n) для множення n-розрядних чисел ..., але це просто не практично.
Корт Аммон

1
Довгий поділ може використовувати паралелізм до будь-якої бажаної міри, обчислюючи приблизну зворотну реакцію, яка при множенні на дільник дає результат від форми 1000 ... xxxx. Під час роботи з дільником у такій формі з N нульовими нулями, це легко обчислити N біт результату з кожним кроком.
supercat

8

У нас може бути кілька шарів логіки на тактовий цикл, але існує обмеження, скільки саме шарів логіки ми можемо мати, наскільки складними можуть бути ці шари, буде залежати від нашої тактової швидкості та нашого процесу напівпровідників.

Однак існує багато різних алгоритмів множення, і я не маю поняття, який може використовуватися мікроконтролерами

У більшості випадків множення в комп'ютерах використовується варіант двійкового довгого множення. Двійкове довге множення передбачає

  • Зміщення одного операнда різними різними сумами
  • Маскування зміщених чисел на основі другого операнда
  • Додавання результатів маскування разом.

Тож давайте подивимось на реалізацію цього в апаратному забезпеченні.

  • Зміна - це лише питання про те, як ми передаватимемо речі, тому це відбувається безкоштовно.
  • Для маскування потрібні І ворота. Це означає один шар логіки, тому з точки зору часу це дешево.
  • Доповнення відносно дороге через потребу в ланцюжку для перевезення. На щастя, є хитрість, яку ми можемо використати. Для більшості етапів додавання, а не додавання двох чисел для отримання одного, ми можемо додати три числа для отримання двох.

Тож давайте балпарк, скільки логічних етапів нам потрібно для множника 8x8 з результатами 16 біт. Для простоти припустимо, що ми не намагаємось оптимізувати той факт, що не всі проміжні результати мають біти у всіх позиціях.

Давайте припустимо, що повний суматор реалізований у два "етапи затвора".

  • 1 для маскування для отримання 8 проміжних результатів.
  • 2 додати групи з трьох чисел, щоб зменшити 8 проміжних результатів до 6
  • 2 додати групи з трьох чисел, щоб зменшити 6 проміжних результатів до 4
  • 2 додати групу з трьох чисел, щоб зменшити 4 проміжні результати до 3
  • 2 додати групу з трьох чисел, щоб зменшити 3 проміжні результати до 2
  • 32, щоб скласти два останні результати.

Отже, загалом близько 46 логічних етапів. Більшість з них витрачаються на складання останніх двох проміжних результатів.

Це можна було б покращити, скориставшись тим фактом, що не у всіх проміжних результатах є всі біти (тобто в основному те, що робить множник Dada), використовуючи суматор несучого пошуку для останнього кроку. Додавши 7 чисел для отримання 3 замість трьох для отримання двох (зменшення кількості ступенів за ціною більше воріт та ширших воріт) тощо.

Це все незначні деталі, але важливим моментом є те, що кількість етапів, необхідних для множення двох n бітних чисел та отримання результату 2n біт, приблизно пропорційне n.


З іншого боку, якщо ми подивимось на алгоритми поділу, ми виявимо, що всі вони мають ітераційний процес, де.

  1. Що робиться за одну ітерацію, сильно залежить від результатів попередньої ітерації.
  2. кількість логічних етапів, необхідних для здійснення ітерації, приблизно пропорційна n (віднімання та порівняння дуже схожі за складністю на додавання)
  3. кількість ітерацій також приблизно пропорційна n.

Отже, кількість логічних етапів, необхідних для здійснення поділу, приблизно пропорційна n квадрату.


Спасибі за вашу відповідь. Я читав у Вікі, що алгоритм тата дуже ефективний, коли мова заходить про необхідну кількість воріт для реалізації цього алгоритму на апаратному забезпеченні. Незважаючи на це, більшість апаратних засобів використовує "двійкове довге множення"?
Марко Гулін

1
Я думаю, що альготих Дади є оптимізованою версією двійкового довгого множення.
Пітер Зелений

Я спалюю 8 циклів, щоб зробити поділ 1 / x. Потім я використовую це для множення 8 циклів за фіксованою вартістю 16 циклів.
б деньян

Це добре показує, що множення не так вже й гірше, ніж додавання.
Хаген фон Ейтцен

1
Ітерація вимагає віднімання, яке можна виконати на етапах O (lgN), використовуючи апаратне забезпечення O (NlgN), або O (sqrt (N)), використовуючи апаратне забезпечення O (N). Однак суттєвим моментом є те, що для множення потрібні етапи O (lgN), тоді як ділення вимагає стадій O (NlgN). Не O (N * N), але більший, ніж множення на коефіцієнт O (N), якщо тільки не починати з приблизної зворотної реакції, щоб дозволити зробити більше роботи за крок.
supercat

4

Алгоритм ділення (насправді будь-який алгоритм) можна скласти за один тактовий цикл. Якщо ви готові платити за додаткові транзистори і нижчу дозволену тактову частоту.

Припустимо, у вас є набір воріт, який реалізує один тактовий цикл існуючого алгоритму поділу багато циклів. Щоб зробити алгоритм одноцикловим, використовуйте декілька етапів апаратного забезпечення (аналогічно тому, що використовується на одній стадії багатоциклового алгоритму), з виходом одного етапу, що подає наступний етап.

Звичайно, причина цього не робити в тому, що він використовує багато транзисторів. Наприклад, для поділу на 16 біт він може використовувати майже 16 X більше транзисторів. Також наявність більше ступенів воріт знижує максимально дозволену тактову частоту (оскільки є більше етапів затримки розповсюдження).


4

Алгоритми практичного поділу базуються на числових наборах, які сходяться до коефіцієнта.

  • Існують адитивні методи, як невідновлення або SRT, який працює, додаючи або видаляючи 2 ^ N до коефіцієнта і відповідно додаючи або видаляючи роздільник 2 ^ N * до часткового залишку, поки він не зведеться до нуля.

  • Існують мультиплікативні методи, такі як Ньютон-Рафсон або Голдшмшир, які є кореневими методами пошуку, де поділ обчислюється як обернення множення.

Аддитивний метод дає один або кілька біт за цикл. Мультиплікативні методи подвоюють кількість бітів за кожен цикл, але потребують деякого початкового наближення, що часто отримується за допомогою постійної таблиці.

Номінали "повільний" і "швидкий" вводять в оману, оскільки фактична швидкість залежить від кількості бітів, скільки апаратного забезпечення присвячено функції (а швидкий множник дуже великий) ...

Ділення відбувається повільніше, ніж множення, тому що немає прямого паралельного методу його обчислення: або відбувається ітерація, або апаратне забезпечення копіюється для здійснення ітерації у вигляді каскадних (або конвеєрних) блоків.


0

Чому апаратне ділення займає так багато часу, ніж множення на мікроконтролері?

Це не питання електроніки. У кращому випадку це питання для комп’ютера, краще адресоване стовпці Overflow.

Дивіться, наприклад, тут: Чи множення швидше, ніж ділення на поплавці?

Насправді це питання з реального життя: Чому поділ займає стільки часу, ніж множення?

Що б ви краще розрахували на папері?

51 * 82

або

4182 / 51

Ділення займає більше часу, ніж множення, тому що це важче зробити .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.