Войти
ФлеймФорумЖелезо

Блеск и нищета 8/16-битных консолей и ПК (22 стр)

Страницы: 121 22 23 2446 Следующая »
#315
13:43, 27 июня 2018

=A=L=X=
Вроде речь то про 8/16 битки. Какие там вещественные? Целочисленные умножения/деления же (с остатком).


#316
(Правка: 14:06) 14:05, 27 июня 2018

Dexus
> Вроде речь то про 8/16 битки.
Ну речь широко зашла.
Взять вот аппаратное умножение - оно ведь тоже может быть не быстрым, а поразрядным (ранее таким и было) и по сути выигрывать только от ликвидации необходимости декодировать команды алгоритма внутри процессора. Это далеко не так быстро чтобы за счёт таких умножений резко выигрывать на делении.
А может быть реализовано на тысячах транзисторов по "мгновенной" схеме - в ранних процессорах такое не использовалось, т.к. огромная по тем меркам сложность схемы, но потом уже во времена пентиумов радостно писали, что мол теперь проще умножить, чем маяться с оптимизациями со сдвигами - работает умножение уже почти как сложение. И правда. С таким умножением действительно можно пересмотреть старые подходы к тому или иному методу.
И вещественное деление пересмотрели. А вот с целочисленным - не получилось, его целочисленность как то вставляла палки в колёса.

#317
(Правка: 14:46) 14:45, 27 июня 2018

=A=L=X=
Ну целочисленное умножение на нескольких тысячах транзисторов за один такт - это в принципе можно представить. А с делением лично мне представить очень сложно - там на каждый разряд условные блоки в алгоритме имеются. Как целочисленное деление с остатком полиномизировать?)

#318
15:30, 27 июня 2018

=A=L=X=
> Лет 10 уже назад читал и тестировал (оказалось правдой), что на FPU x86 эпохи всяких пентиумов 2 или 3 деление работало почти так же быстро как умножение, потому что работает оно там через reciprocal+mul
Вообще-то, основная сложность тут как раз в нахождении 1/x, умножением на его фоне можно пренебречь.

> Но при этом целочисленное умножение этому трюку не поддавалось и работало медленнее всех арифметических операций, включая вещественные.
Вообще-то, если есть вещественное 1/x с достаточной точностью, то сделать соответствующее целочисленное деление не представляет проблем.
Основная разница тут в том, что для float деления надо 24 двоичных разряда, а для int — уже требуется 32.

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

Dexus
> А с делением лично мне представить очень сложно - там на каждый разряд условные блоки в алгоритме имеются.
Не, в принципе в железе можно реализовать все: разложить алгоритм на длинный конвейер, где каждая стадия делает по одному шагу алгоритма.
Например: сдвиг до единицы в старшем разряде, таблица начальных приближений 1/D, несколько шагов Ньютона, умножение на числитель, проверка и коррекция целочисленного результата.
Но вот загрузка такого аппаратного делителя будет крайне низкой, поэтому никакого смысла его делать нет, лучше задействовать уже существующие блоки с помощью микрокода.

#319
16:56, 27 июня 2018

}:+()___ [Smile]
> Вообще-то, основная сложность тут как раз в нахождении 1/x

Имелось ввиду что reciprocal быстрый на фоне честного деления - он вроде бы через эти же умножения сам и делается.

> Основная разница тут в том, что для float деления надо 24 двоичных разряда, а для int — уже требуется 32.

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

#320
16:56, 27 июня 2018

Вроде же в x86 целочисленное и вещественное деление (64:64->64) выполняется одной и той же железкой (делилкой FPU) в большинстве процов.
И целочисленное чуть медленнее, из-за разной обвязки.
А беззнаковое - ещё медленнее.

Про более короткие - хз.

}:+()___ [Smile]
> Я такое называю не аппаратной поддержкой, а реализацией через микрокод.
И serial shifter - это по-твоему тоже микрокод?

#321
17:45, 27 июня 2018

Хотя хз.
https://mobile.twitter.com/rygorous/status/603347794418511874
https://twitter.com/rygorous/status/590645644110475268

#322
20:49, 27 июня 2018

=A=L=X=

ты откуда всё это знаешь?

#323
22:41, 27 июня 2018

=A=L=X=
> вещественные числа еще нормализованы и это тоже даёт пространство для сильных оптимизаций
Есть еще и денормалы, у которых та же проблема, что и у целых. Правда, часто на них забивают и сваливаются в микрокод.

> плюс еще они в принципе допускают неточности в последних битах
Если ошибка такая, что дает всего два варианта целочисленного ответа, условно [cht]\lfloor N/D\rfloor[/cht] либо [cht]\lceil N/D\rceil[/cht], то потом одной проверкой остатка можно получить точный результат, заодно выбрав необходимое направление округления.

FordPerfect
> И serial shifter - это по-твоему тоже микрокод?
На мой взгляд, да. Есть некая железка, которая выполняет элементарную операцию, и поверх нее реализован более сложный многостадийный алгоритм.
То, что в данном случае программа простая и реализована не в readonly памяти а на фиксированной логике, ничего принципиально не меняет.
В общем, если железка не тянет throughput в одну инструкцию за такт, я называю это микрокодом.

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

#324
6:03, 28 июня 2018

Хаус
> ты откуда всё это знаешь?

Это - что? Про 8 бит? В детстве был спектрум и денди, хотя я не особо был в них крут. Но давно уже когда интернеты сделали всю информацию доступной искал да почитывал всякие штуки. А с момента создания этой темы тут стал просто активнее почитывать.
Вот как следующий комм будет...

#325
(Правка: 29 июня 2018, 13:51) 7:02, 28 июня 2018

Библиотека калькулятора ZX Spectrum

Наткнулся на описание того как работает библиотека калькулятора в ZX Spectrum (как и многие книжки той эпохи она просто кишит опечатками и ошибками). Текста там много, так что тут вкратце опишу как оно всё работало, ибо это действительно забавно.
Итак, в ПЗУ ZX Spectrum был прошит интерпретатор Basic и как любой приличный бейсик он мог работать с числами с плавающей точкой.
Центральный 8-битный процессор Z80 не обладал поддержкой вещественных чисел, поэтому солидный блок ПЗУ содержал программную эмуляцию работы с ними.
Сами вещественные числа в ZX были 5-байтными. В первом байте содержалась увеличенная на 128 экспонента, а в следующих 4-х байтах - мантисса.
Но вот вызов процедур по работе с вещественными числами был оформлен довольно необычно (имхо).
Точкой входа в процедуры являлась инструкция процессора RST 28, то есть однобайтовое сокращение CALL $0028. Однако данная точка входа не ожидала от вызывающего кода передачи параметров в регистрах, как это часто бывает, совсем даже нет. Вместо этого она начинала анализировать последовательность байт по адресу на вершине стека (то есть с адреса куда надо возвращаться из процедуры) и интерпретировать их как однобайтовые коды команд стекового калькулятора!
Стек калькулятора находится в конце занятой программой и переменными бейсика памяти и растёт не сверху-вниз, а снизу-вверх, по сути - навстречу классическому стеку процессора. Стек калькулятора содержит 5-байтные вещественные числа, которые, правда, еще могут восприниматься строки (тогда в двух байтах хранится адрес начала строки, а еще в двух - её длина) или целые числа (если вкратце, то тогда экспонента равняется нулю, а само число хранится в двух средних байтах). Кроме того логические операции трактуют числовой 0 как FALSE, а всё кроме нуля - как TRUE.
В полном соответствии со стековыми вычислителями команды калькулятора могут помещать или убирать число на вершину стека, дублировать вершину, совершать с двумя числами на вершине арифметическую операцию замещая их одним числом результата и т.д., и т.п.
Полную таблицу кодов команд калькулятора можно посмотреть тут
Я опишу немного самых актуальных вещей (код команды дан в шестнадцатеричном виде):

01 - обмен двух чисел на вершине стека
02 - отбрасывание вершины стека
31 - дублирование вершины стека
...
0F - сложение двух числе на вершине (результат замещает их)
03 - вычитание
04 - умножение
05 - деление
06 - возведение в степень
1F - синус (результат замещает аргумент на вершине)
20 - косинус
21 - тангенс
...
17 - конкатенация двух строк на вершине
...
07 - X OR Y - логическое "ИЛИ"
...
A0 - втолкнуть на вершину 0
A1 - втолкнуть на вершину 1
A2 - втолкнуть на вершину 0.5
A3 - втолкнуть на вершину Pi/2
A4 - втолкнуть на вершину 10
...
34 - втолкнуть на вершину произвольное число
     (помещается в упакованной форме после кода)
...
C0-C5 - сохранить вершину стека во временную ячейку M0-M5
D0-D5 - втолкнуть на вершину временную ячейку M0-M5
...
2A - abs( x ) - функция бейсика модуля числа
2B - peek( x ) - функция бейсика peek
2D - usr( x ) - функция бейсика USR (вызов машинного кода)
...
3B - execute B - выполнить инструкцию калькулятора с кодом из регистра "B" 
     (берется при входе в калькулятор из одноимённого регистра ЦП)
...
33 - безусловный переход на байт со знаком (хранится после кода команды)
00 - условный переход (как 33) если число на вершине = TRUE
38 - возврат из калькулятора
После встречи инструкции 38 процедура обработки калькулятора возвращала управление машинному коду располагающемуся сразу за байтом с этой инструкцией. То есть получалось, что машинный код как бы перемежался с интерпретируемыми инструкциями калькулятора, при этом при возврате из калькулятора в регистре HL сохранялся адрес первого байта числа на вершине стека.
Инструкции калькулятора покрывают всё множество функций бейсика и кроме того содержат множество вспомогательных вещей для промежуточных вычислений разнообразных математических функций.
Рассмотрим следующий ассемблерный код на ZX Spectrum:
RST 28 ; входим в калькулятор
DB $A1 ; FPUSH 1
DB $A2 ; FPUSH 0.5
DB $0F ; FADD
DB $38 ; FEND
Эта последовательность инструкций приведёт к тому, что в HL окажется указатель на вершину стека с вещественным числом 1.5.
(теперь очевидно, что именно делал код из пакета Hisoft C который я приводил в спойлере тут)
Но обратите внимание, что в этих инструкциях есть даже условные переходы, то есть на данных кодах калькулятора можно реализовывать произвольные числодробительные алгоритмы, а не только считать синусы с косинусами. Причём из калькуляторного кода можно вызывать машинный код функцией USR бейсика.

Эта естественность с которой инструкции калькулятору можно впрячь в машинный код невольно подталкивает к очевидной мысли - теоретически можно сделать математический сопроцессор для ZX Spectrum реализующий эти команды в железе! Более того - существующий код того же встроенного интерпретатора Basic сможет получить буст в скорости совершенно без внесения каких либо изменений!
Это не только забавно, но и мысль сия действительно приходила в голову людям и ранее: https://github.com/cheveron/sebasic4/wiki/X80-Math-Co-processor

#326
14:53, 28 июня 2018

=A=L=X=
> Но вот вызов процедур по работе с вещественными числами был оформлен довольно
> необычно (имхо).
Когдa у меня появился «ZX-Spectrum» и я более-менее его изучал, этот «RST 28» не выглядил как-то необычно, так как из «РАДИО-86РК» я уже знал подобные приёмы…
А из справочников по процессорам я увидел сходство с i8086/i8087…

> Это не только забавно, но и мысль сия действительно приходила в голову людям и
> ранее: https://github.com/cheveron/sebasic4/wiki/X80-Math-Co-processor
Тaк… Стоп………
Как это «X80-Math-…»???
Этот «X…» перечёркивает мой x80 же!!!

P.S.: Вот ведь неприятный сюрприз…
Что, теперь придётся весь мой проект переименовывать? O_o

#327
14:57, 28 июня 2018

=A=L=X=
> В первом байте содержалась увеличенная на 128 экспонента, а в следующих 4-х
> байтах - мантисса.

я как бы помню что в первом был знак ?

раскажи про Forth на Speccy

#328
15:10, 28 июня 2018

Alikberov
> P.S.: Вот ведь неприятный сюрприз…

Да там всё равно просто предложение сделать очевидное, чисто идея по полочкам разложенная, но в железе оно не реализовано, так что нечего там стесняться.

innuendo
> я как бы помню что в первом был знак ?

Знак был в первом бите мантиссы, при том, что ввиду её нормализованности всегда предполагается неявный единичный бит сразу после (или даже "под") бита знака, ну как это в float полагается.

#329
15:23, 28 июня 2018

=A=L=X=
> Это - что?

столько инфы про внутреннее устройство устройств, какие книжки пересказываешь?

Страницы: 121 22 23 2446 Следующая »
ФлеймФорумЖелезо