Флейм
GameDev.ru / Флейм / Форум / Меряемся придуманными машинными архитектурами (3 стр)

Меряемся придуманными машинными архитектурами (3 стр)

Страницы: 1 2 3 4 5 6 7 Следующая »
Dmitry_MilkПостоялецwww25 ноя. 201720:27#30
=A=L=X=
> но тема про любую экзотику тоже.

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

Буду описывать не архитектуру сразу, а начну с истории, потому что иначе, боюсь, непонятно будет, зачем вообще это все надо (было) (мне).

Идея такой вычислительной архитектуры (ну или точнее одного из способов реализации) возникла у меня лет 13-14 назад, когда я только-только узнал про нейронные сети и был по началу излишне очарован ими (были мысли типа "О! так люди уже знают, как устроен/работает мозг???!!!"). Впрочем, уже тогда было понятно, что мы еще чего-то не знаем о биологических нейронах (как позже понял, знаем вообще очень мало для того, чтоб эмулировать настоящие нервные системы, а тем более мозг млеков и человека).

Эмуляция чего-то большого на компах тогда казалась слишком уж невероятной (не было тогда еще бума облачных вычислений). Про аппаратные средства для моделирования нейросетей тогда уже возникали время от времени заявления от разных производителей, но было понятно, что это средства именно для "слишком формальных нейронов". Тогда и появилась у меня фан-мысль: а вот было бы здорово, если б можно было эти модели "выращивать", не возясь с каждым нейроном и синапсом по-отдельности, а просто задавая какие-то общие правила, подчиняясь которым нейроны росли бы и как-то соединялись, но не в эмуляции на фонНеймановском компе, на на специализированной параллельной аппаратуре.

Примерно тогда же я интересовался игрой Жизнь - было прикольно, что люди умудряются там конструировать достаточно сложные целенаправленные конструкции, типа "паровозов" или "глайдерных ружей" (упомянутый в сообщении выше метапиксель тогда еще не был придуман). И было понятно, что если не ограничиваться жесткими рамками конвеевских правил, если допустить больше двух состояний и произвольные правила переходов состояний, то можно не только "выращивать" из "зародышей" какие-то бесполезные конструкции на решетке, но и заставить эти конструкции выполнять какие-то полезные действия/вычисления, просто добавив еще дополнительных состояний для каждого элемента. (Пример самого элементарного "выращивания" некоторой абстрактной "бактерии", состоящей из "мембраны" и "внутренней полости" есть в документе в архиве. Там же есть и пример двоичного параллельного сумматора).

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

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

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

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

Вот архив (html с картинками - ca_slops) с более подробным описанием и примерами. Вариант предложенной там аппаратной реализации был вполне обоснованно раскритикован теми, кто удосужился этот поток сознания прочитать - слишком длинные и огромные вязанки параллельных проводов, по которым подразумевается передача высокочастотного параллельного кода. Получившаяся на них емкость накрывет всю идею медным тазом.

После этого идея была заброшена (да и не могла она привести ни к чему, это был просто фан, чтоб потешить ЧСВ). Сейчас тем более в ней нет смысла - всякие нейросети лубой сложности моделируются в облаках только так. Но если б вдруг понадобилось ее возродить (например, там в статье есть идея еще для одного применения, "нанотехнологии" а-ля "жидкий терминатор", но надо какой-то наномеханизм для управляемой механической связи элементов с соседями), я б наверное сейчас пошел немного другим путем - широковещание последовательным кодом с помощью пучка модулированного света на весь кристалл - так и частоты можно получить гораздо выше, до десятков ГГц, и ни одного длинного параллельного провода (кроме шин питания), только локальные связи длиной не более размера одного элемента.

kiparУчастникwww27 ноя. 201714:17#31
Sbtrn. Devil
> Написать на ней минимально самореплицирующуюся программу пока не довелось, ибо
> не было смысла. Но кто запрещает попробовать это вам, дорогие читатели?
18 слов:
  0, 4160, 6337, 2, 1152, 17472, 6273, 1000, 17440, 4160, 6337, 10, 14465, 1, 22593, 18, 17602, 982

общего вида, т.е. копирует фрагмент памяти длиной в 16-м байте (18) на указанное в a18 расстояние (1000) и передает управление на (1000-18 = 982) байт вперед. Эмулятор не писал, так что вполне могут быть опечатки.
+ Показать


На архитектуре =A=L=X= у меня получилось 36 байт:

a1,a2,a3      R2W = 1000      # назначение
a4,a5         R3B = 36        # длина
a7,a8         R6B = 0         # счетчик
a9, a10       R7 = R2-R3      # расстояние перехода  
a11,a12,a13   R8W = -14       # R8 = -14 (длина цикла копирования)
a14,a15,a16   R1W = -17       # 
a17           ACC -= R15      # R1 = a18-17 = a1
a18           R4 = ACC        # R4 = a1 (SRC)
a19           ACC += R2       # 
a20           R5 = ACC        # R5 = a1+1000 (DEST)
loop:
a21,a22       R1 = [R4++]     # R1 = [SRC++]
a23,a24       [R5+R6] = ACC   # [DEST+счетчик] = R1
a25,a26       ACC = 1B        #
a27           ACC += R6       # R1 = счетчик+1
a28           R6 = ACC        # load back to counter
a29,a30       ACC ?= R3       # compare with длина
a31,a32       IF NOT_EQUAL    #
a33,a34       R15 -= R8       # if not equal - jump back to a35 - 14 = a21
a35,a36       R15 += R7       # otherwise, jump forward to R7
ну тоже наверное можно сократить.
показалось неудобным что для загрузки отрицательных чисел надо всегда грузить слово (т.е. скажем R1 = R2-1 займет 4 байта а R1 = R3+1 - только 3), ну и возможно я не совсем понял идею декрементов, потому что копирование памяти получилось не таким и коротким (в аккумулятор надо кидать то данные, то счетчик для условия).
ассемблировать не стал т.к. регистр флагов не расписан, если там нет not_equal, то печаль, я сделал чтоб команда передачи управления вперед была последней (как и в версии на Sbtrn. Devil) чтоб сэкономить на одной загрузке отрицательного числа, а так еще +4 байта будет.

Kollect3DПостоялецwww27 ноя. 201714:36#32
kipar
> т.е. скажем R1 = R2-1 займет 4 байта а R1 = R3+1 - только 3

=A=L=X=
> При загрузке одного байта он загружается в нижнюю половину регистра, верхняя
> при этом дополняется его верхним битом (расширение со знаком).
> ...
> 1. += data4 сложение с константой - поле аргумента XXXX исходной команды
> воспринимается не как номер регистра, а как число от 1 до 16

kiparУчастникwww27 ноя. 201716:14#33
да, так намного удобнее.
28 байт
a1,a2,a3      R2W = 999       # назначение-1
a4,a5         R3B = 28        # длина
a6            ACC = R15       # R1 = a11
a7,a8         ACC -= 8        # R1 = a9-8 = a1
a9            R4 = ACC        # R4 = a1 (SRC)
a10, a11      R3 += R1        # R3 = SRC+длина (окончание буфера)
a12           ACC += R2       # 
a13,a14       ACC += 1        #
a15           R5 = ACC        # R5 = a1+999+1 (DEST)
loop:
a16,a17       ACC = [R4++]    # R1 = [SRC++]
a18,a19       [R4+R2] = ACC   # [SRC+999] = R1
a20,a21,a22   R4 ?= R3        # compare with R3
a23           IF LESS         #
a24,a25,a26   R15 -= 11       # if not equal, jump back to a27 - 11 = a16
a27,a28       R15 = R5        # if equal, jump to R5

Правка: 27 ноя. 2017 16:20

Kollect3DПостоялецwww27 ноя. 201718:00#34
kipar

Можно на 1 байт уменьшить тело цикла копирования:

R1=DST
R2=SRC
R3=CNT - 1
R4=1
LOOP:
(2) ACCB=[R3+R2]
(2) [R3+R1]=ACCB
(2) R3-=R4
(4) IF NOT-CF R15-=10
(в скобках число байт)
Вообще забавно получается, чтобы скопировать 1 байт данных процессору надо прочитать 10 байт программы, то есть КПД RAM скажем так один к пяти.
Проверил как с этим обстоят дела у современного x86-64 на https://godbolt.org/ - оказалось что GCC с -O2 делает на нём тело цикла длиной 16 байт.
Ахренеть. Да, понятно зачем у старых процов были зачастую команды блочного копирования.

Правка: 27 ноя. 2017 18:01

=A=L=X=Постоялецwww28 ноя. 20173:17#35
kipar
> не совсем понял идею декрементов

Это для реализации стека полезно, PUSH/POP считай что готовые.

Kollect3D
> Вообще забавно получается, чтобы скопировать 1 байт данных процессору надо
> прочитать 10 байт программы

Причём это неплохой показатель! :D Во первых, если запихать константу 10 в регистр, то тело цикла можно ужать до 9 байт.
Во многих 8/16-битных процессорах действительно были всякие блочные команды типа LDIR или REP STOSB, но посмотрим на те где этого не было.
MOS 6502: http://6502.org/source/general/memory_move.html этот процессор был 8-битным настолько насколько это вообще возможно - он даже цикл длиннее 256 итераций вынужден был разбивать на двойной цикл по 256 итераций во внутреннем подцикле.
Но хуже того - все его 8-битные 3 регистра общего назначения просто не могли хранить адрес, поэтому адрес хранился в памяти и там же и инкрементировался побайтно - таким образом даже самое короткое тело цикла в 7 байт отягощено считываем двух адресов по 2 байта из памяти давая 11 байт считываний из памяти на 1 пересылаемый байт.
Intel 8080: https://en.wikipedia.org/wiki/Intel_8080 статья на вики содержит как раз процедуру momcpy и тело цикла в ней 10 байт. Предшественнику Z80 байт портит то, что инкременты/декременты слов не меняют регистр флагов, поэтому тестировать счетчик цикла на ноль приходится отдельными 8-битными командами с аккумулятором.
Так что по плотности кода memcpy этот мой проц вполне себе так ничего. :)

=A=L=X=Постоялецwww4 дек. 201715:28#36
В общем посмотрел я на всякие разные 8-битки и вызрело у меня чувство, что в сабже пытаться опкод уместить в одном байте - вещь бесплодная и антипаттерновая.
Границу надо раздвинуть до 2-х байт минимум. Ведь даже у 6502 zero-page был минимум 2-хбайтовой командой, так что процу с 15 РОН вообще не стоит парится по этому поводу.
Однобайтовые префиксы останутся конечно, но их надо ограничить условиями, очень уж удобно это, и какими-то утилитарными вещами типа там задел под подключение сопроцессоров.

Правка: 4 дек. 2017 15:29

clcПостоялецwww4 дек. 201718:26#37
да, на одном байте сложно что-то сделать, сильные зависимости. Переменная длина кодов без чёткой границы перехода затрудняет эмуляцию.
AlikberovПостоялецwww22 мая 201813:44#38
Смoтрю, оказывается я единственный, кто смог свою задумку набросать в рабочий эмулятор, состряпать ассемблер, да ещё написать какой-никакой BIOS.
+ Онлайн студия разработки своей архитектуры

P.S.: (Какой я скромняжка)

Правка: 22 мая 2018 16:41

TonalПостоялецwww23 мая 20181:15#39
=A=L=X=
Если допустить некоторую специализацию регистров то можно шире использовать неявную адресацию, сэкономив один или два бита в таких командах на выбор регистра в пользу опкода.
Например зачем нам одновременно для всех регистров возможность быть источником адреса для косвенной адресации?
Пусть таких регистров указателей будет 8 из 16(сэкономили один бит), используем этот бит для выбора второй половины регистров например в коммандах умножения и деления.
Итого имеем 16РОН равноправных например при прямой адресации регистров в коммандах простой арифметики и логики, и по 8 независимых регистров для комманд косвенной адресации и умножения/деления.

Правка: 23 мая 2018 1:22

daveПостоялецwww23 мая 20181:20#40
Сто тыщ кубит и Эксабaйт памяти.
TonalПостоялецwww23 мая 20181:25#41
dave
100^500!
TonalПостоялецwww23 мая 20181:38#42
=A=L=X=
> Предшественнику Z80 байт портит то, что инкременты/декременты слов не меняют
> регистр флагов, поэтому тестировать счетчик цикла на ноль приходится отдельными
> 8-битными командами с аккумулятором.
DJNZ  Rn, #ad - decrement and jump if not zero, в нормальных архитектурах это обычно одна команда. то что флаги не портит ей только в плюс

Ну и комманды сравнения регистров с константой(чтобы также не таскать через аккумулятор) мастхэв!
CJNE  Rn, #d , #ad - compare and jump if not eqivalent

Хорошая команда JMP @A+РС или JMP @A+Rn,  чтобы ветвится быстро)

ЗЫ:
# - знак константы
@ - знак косвенной адресации

вот так например выглядит копирование блока внутренней(256байт) памяти на 8-бит архитектуре 8051

  MOV    R0, #SOURCE  ; 8-битный адрес источника
  MOV    R1, #DEST  ; 8-битный адрес приемника
  MOV    R2, #N    ; длина блока

MCP:
  MOV    A, @R0    ; чтение байта по адресу источника    1байт 1маш.цикл
  MOV    @R1, A    ; запись байта по адрему приемника  1байт 1маш.цикл
  INC    R0      ; инсремент указателя источника    1байт 1маш.цикл
  INC    R1      ; инсремент указателя приемника    1байт 1маш.цикл
  DJNZ    R2, #MCP    ; цикл копирования          2байт 2маш.цикл

а так выглядит копирование блока внешней(64кб) памяти на 8-бит архитектуре 8052

  MOV    DPTR, #SOURCE; 16-битный адрес источника
  MOV    DPTR1, #DEST  ; 16-битный адрес приемника
  MOV    R2, #N    ; длина блока

MCP:
  MOVX  A, @DPTR    ; чтение байта по адресу источника    1байт 2маш.цикл
  MOVХ  @DPTR1,  A  ; запись байта по адрему приемника  1байт 2маш.цикл
  INC    DPTR      ; инсремент указателя источника    1байт 1маш.цикл
  INC    DPTR1    ; инсремент указателя приемника    1байт 1маш.цикл
  DJNZ    R2, #MCP    ; цикл копирования          2байт 2маш.цикл

Длина блка здесть такде ограничена 256байт, для больших значений длины блака два 8битных регмстра и две команды DJNZ  подряд

DJNZ    R2, #MCP
DJNZ    R3, #MCP

Кто из 8-биток сможет быстрее?

Уоригинального 8051 был только один недостаток - длинный машинный цикл, 12тактов внешнего генератора...
Впоследствии несколько компаний независимо друг от друга выпустили ядра полностью програмно совместимые с 8051 и длительностью машинного цикла 1 такт внешнего генератора, большинство команд выполняется за 1маш.цикл

Правка: 23 мая 2018 3:39

TonalПостоялецwww23 мая 20184:30#43
Для коротких и быстродействующих обработчиков прерываний сохранение портящихся регистров в стеке PUSH/POP(2 маш.цикла на команду) непозволительная роскошь...
В то же время команда XCH A, ad(обмен значений А и байта в ОЗУ) выполняется за 1маш.цикл, и может быть совмещена с инициализацией.

Сравним, обработчик прерывания СОМпорта
В первом примере все по канону, но большинство команд двух.тактовые и сравнение портит регистор флагов

+ Показать

И не по канону, но почти в два раза быстрее

+ Показать

В случае коммуникаци на высокой скорости без управления потоком это вопрос успеем ли мы обработать текуший байт пока не пришел следующий)

Правка: пересчмитал и поправил время исполнения

Правка: 23 мая 2018 5:13

=A=L=X=Постоялецwww23 мая 20186:03#44
Tonal
> Пусть таких регистров указателей будет 8 из 16(сэкономили один бит), используем
> этот бит для выбора второй половины регистров например в коммандах умножения и
> деления.
Это в точности подход Motorola 68000 - 16 РОН делится на 8 регистров данных и 8 регистров адреса. Между ними возможны пересылки, но полная арифметика возможна только над первыми, а косвенная адресация - только через вторые.
Страницы: 1 2 3 4 5 6 7 Следующая »

/ Форум / Флейм / Железо

2001—2018 © GameDev.ru — Разработка игр