nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

Испытания новой АЛУ, перемножение матриц

Третья часть "аффинного алгоритма", умножение матрицы 3x4 (из ПЗУ, посчитана заранее) на матрицу 4x2, составленную из наших 4 точек, обнаруженных на фотоприёмной матрице и правильным образом расставленных. Результатом, очевидно, становится матрица 3x2 аффинного преобразования: "матричная часть" 2х2, отвечающая за масштаб, крен и ракурсы, и "векторная" 1x2, отвечающая за параллельный перенос. Вот наш код:

;состояние регистров к этому моменту
;Y = Points2D
;X = Fx3
;Z = Fx2
;i=j=k=0
;Inv неизвестен
;C, Acc - неважно
Compute4PointAffine	proc
		X		AffineMat
		Z		Matrix ;вообще AfTransf, но это промежуточная матрица, её занесём сюда (пока не наступило сопровождение, эти ячейки напрочь не нужны!)
	;по сути, Z = X * Y, где все операнды - матрицы.
		k		1	;номер строки результата (и строки AffineMat)
@@k_loop:	j		2	;номер столбца результата (и столбца Points2D)
@@j_loop:	i		3	;номер столбца AffineMat и строки Points2D
		ZAcc		RoundZero	;обнулить до 1/2 мл. разр
@@i_loop:	C		[X+4j+i]
		FMA		[Y+2i+k]
		iLOOP		@@i_loop
	;очередной результат готов...
		[Z+2j+k]	Acc
		jLOOP		@@j_loop
		kLOOP		@@k_loop
;вот, какбе и всё...	
Compute4PointAffine	endp


Чувствую, что здесь новая АЛУ покажет свой потенциал!


В кои-то веки, пока выполняется длительное "умножение с накоплением" (Fused Multiply-Add, FMA), мы успеем перейти в начало цикла, на последнем такте загрузить регистр C, и начать следующее. В итоге, на каждой итерации мы экономим 3 такта на прыжке и ещё 1 на "C". Всего внутренний цикл выполняется 24 раза, так что ожидаем экономии чуть менее 96 тактов, и это на общем фоне довольно ощутимо. Скажем, если одна итерация внутреннего цикла требовала 22 такта (18 на FMA, 1 на C и 3 на iLOOP, учитывая сброс конвейера), а теперь исполняется за 18, это экономия 22%. На деле чуть меньше, скоро увидим.

Как-то улучшить этот код вряд ли получится, разве что загнать строку "Z Matrix" из начала процедуры в цикл, непосредственно перед записью результата, поскольку там эта строка выполнится "нахаляву" (всё равно дожидаться АЛУ), на этом мы сэкономим аж ОДИН такт :) Ну давайте из жадности так и сделаем. Результат покажем уже на листинге.

Сначала исполним имеющийся код на старом АЛУ. Получающиеся результаты:


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

Выполняется эта процедура за 24,28 мкс, или 607 тактов. Нда, код маленький, но когда три вложенных цикла - выполняться он может прилично...

Теперь попробуем исполнить на новом АЛУ чуть подправленный код, вот его листинг:

    Compute4PointAffine proc
27  CD0F                  X           AffineMat
28  A204                  k           1           ;номер строки результата (и строки AffineMat)
29  A10B      @@k_loop:   j           2           ;номер столбца результата (и столбца Points2D)
2A  A003      @@j_loop:   i           3           ;номер столбца AffineMat и строки Points2D
2B  8803                  ZAcc        RoundZero   ;обнулить до 1/2 мл. разр
2C  8AC7      @@i_loop:   C           [X+4j+i]
2D  92D9                  FMA         [Y+2i+k]
2E  A810                  iLOOP       @@i_loop
2F  ED11                  Z           Matrix      ;вообще AfTransf, но это промежуточная матрица, её занесём сюда (пока не наступило сопровождение, эти ячейки напрочь не нужны!)              
30  EA80                  [Z+2j+k]    Acc
31  A912                  jLOOP       @@j_loop
32  AA13                  kLOOP       @@k_loop
    Compute4PointAffine endp



С первого раза всё выполнилось правильно (результаты совпали до бита) и заняло 498 тактов вместо 607, или на 18% меньше! Это даже лучше, чем я ожидал.
[Spoiler (click to open)]Похоже, на старом АЛУ мы здесь собрали все "невзгоды" сброса конвейера: когда мы прыгали в начало цикла, первой начинала "в одиночку" выполняться команда SrcAddr: [X+4j+i], занимая 2 такта. Затем выполнялась [Y+2i+k], также 2 такта, задерживая команду "С" на лишний такт, и только потом начиналось умножение с накоплением. Только когда оно целиком заканчивалось, мы выполняли iLOOP, затем один такт уходил целиком "на помойку" (не выполнялась ни SrcAddr, ни DestAddr), итого на одну итерацию получалось 24 такта, а с новой АЛУ время сократилось до 18 тактов, т.е без учёта всех прочих "накладных расходов". Похоже, считать надо количество прыжков из внутреннего цикла, их число равно 3 * 3 * 2 = 18. В каждом из них мы сэкономим по 6 тактов (24 - 18), что даёт 108 тактов. И ещё один экономится на переносе "Z Matrix" внутрь цикла, итого 109. Как в аптеке!

Следующая на очереди: процедура выделения крена из этой матрицы аффинного преобразования.
Tags: ПЛИС, программки, работа, странные девайсы
Subscribe

  • А всё-таки есть польза от ковариаций

    Вчера опробовал "сценарий", когда варьируем дальность от 1 метра до 11 метров. Получилось, что грамотное усреднение - это взять с огромными весами…

  • Так есть ли толк в ковариационной матрице?

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

  • Big Data, чтоб их ... (4)

    Наконец-то стряхнул пыль с компьютерной модели сближения, добавил в неё код, чтобы мы могли определить интересующие нас точки, и выписать…

  • Очередная несуразность в единицах измерения

    Когда-то я написал программу PhysUnitCalc - калькулятор, умеющий работать с размерностями. Мне казалось, что я наступил уже на все грабли, которые…

  • Big Data, чтоб их... (3)

    "В предыдущих сериях": мой прибор выдаёт 6 значений: 3 координаты и 3 угла, т.е все 6 степеней свободы твёрдого тела. Причём ошибки измерения этих 6…

  • Big Data, чтоб их... (2)

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

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments