nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

Алг.обнаружения, работа над ошибками

Прежде чем продолжить отладку, надо исправить все обнаруженные ошибки. Самая первая - наиболее незначительная - "ошибка на единицу" в нумерации Y, из-за чего приходится "дополнительные умственные усилия" прикладывать, что на полученном изображении 197, а в дампе памяти это 198. Тут всё просто, строку

[SP+2j]	0		;в [SP+2] храним номер строки.


заменяем на

[SP+2j] -1		;в [SP+2] храним номер строки.


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

И также "не глядя" заменяем неправильное условие:

JL		@@RemoveBlob	;уже далеко, пора его удалять!


на

JGE		@@RemoveBlob	;уже далеко, пора его удалять!


Дальше, чуть менее очевидное исправление с регистрами после слияния пятен.

Вот как выглядит код, который запускает "операцию со списками":

;теперь удаляем правое пятно
	Y	X
	X	Heap
	[SP]	@@EndOfCycle
	JMP	MergeBlobCase


Здесь MergeBlobCase - это "точка входа" в ListOp, чтобы чуть сэкономить такты:

;взять первый элемент из списка Y и перецепить его в начало списка X
;значения X,Y остаются неизменными,
;при вызове должно быть k=0, затираем регистр Z, Acc и флаг знака
;адрес возврата хранится в стеке, как положено
	ListOp proc			
		Z	[Y+k]
		ABS	[Y+k]
MergeBlobCase:	[Y+k]	[Z+k]
		JO	OutOfMemory									
		[Z+k]	[X+k]
		[X+k]	Z
		NOP	0		;избежать Memory hazard (одновременный доступ на чтение и запись)
		JMP	[SP]
	ListOp endp	


И опять устаревшие комментарии - флаг знака больше НЕ ЗАТИРАЕТСЯ!

И сейчас так организовано, что из этой процедуры мы "выскакиваем" сразу куда надо, в @@EndOfCycle, это место, где мы проверяем отрезок "под пятном". В данном случае, под "правым" пятном, которое только что слилось с левым. Там регистр X должен указывать на это самое пятно, а регистр Y - на предшествующее ему. Так что "выскакивать" сразу куда надо нам нельзя, нужно вернуться и поменять регистры. Так что вызов будет выглядеть так:

	;теперь удаляем правое пятно
	Y	X
	X	Heap
	[SP]	CALL(MergeBlobCase)
	X	Y
	JMP	@@EndOfCycle


Теперь по крайней мере регистр X будет указывать куда надо. А вот регистр Y совсем "правильно" присвоить очень затруднительно - мы хорошо передвигаемся по этому списку "слева направо", а в данном случае нужно сдвинуться левее! Но правильное значение регистра Y нужно только в том случае, если мы захотим переместить пятно из списка ActivePoints в AllPoints, из-за того что мы уже ушли гораздо ниже его. Но мы не меняли Y-координаты левого пятна, а ранее на этой строке уже проверили его и перемещать НЕ ПОЖЕЛАЛИ! Значит, пущай остаётся каким угодно.

Так что подобный код должен сработать, добавилась ещё одна строка...

И теперь самое весёлое, подправить коррекцию параметров пятен по мере "поглощения" точек вблизи себя

Во-первых, посмотрим, не исправится ли всё, если мы поставим D1=4? Тогда вокруг пятна с координатой X мы будем давать одно задание грубо говоря [0;X-3] (слева от пятна), следующее [X-1;X+1] (под пятном), и [X+3; ...] справа от пятна.

Допустим, мы нашли новую точку аккурат на X+3. Проверка на слияние: X+3-X-D1 = -1 - пройдена.
Теперь диаметр точки заменится на (X+3)-X+D/2 = 5 - расширение пока идёт.
А координата центра станет равна (X+3) - D'/2 = X+0,5, что при сохранении в память "обрежется" до X, т.е пятно останется стоять на месте.

А к следующему разу, когда диаметр пятна станет 5, мы будем давать задание [0;X-4] (слева от пятна), [X-2;X+1] (под пятном) и [X+3; ...] справа от пятна.

И если мы найдём точку на X+3, проверка на слияние (X+3)-X-5/2-4/2 = -1,5 - пройдена.
Диаметр точки заменится на D'=(X+3)-X+D/2=5,5 - это так и останется 5, т.е расширение опять "зачахнет".
А координата центра станет равна (X+3) - D'/2 = X+0,5 - так что и двигаться вправо пятно не будет.

Совершенно нахаляву можно хоть сколько-нибудь сдвинуть дело с мёртвой точки. Сейчас обновление параметров выглядит так:

	Acc		[SP+1]		;Acc = x, т.е координата обнаруженной точки
	SUB		[X+2j+k]	;вычитаем X, т.е Acc = x - X - разность между обнаруженной точкой и центром левого пятна
	DIV2A		[X+1]		;прибавили D/2, получаем Acc = x-X+D/2 
	[X+1]		Acc		;обновили диаметр левого пятна.
	NOP		0
	;теперь подкорректировать X-координату
	Acc		[SP+1]		;берём координату обнаруженной точки
	DIV2S		[X+1]		;вычитаем половинку диаметра
	[X+2j+k]	Acc

NOP здесь появился, поскольку иначе будет одновременное чтение из памяти в [SP+1] и запись в память [X+1] - это "незаконно", и хотя компилятор сам догадается и вставит Hazard, я предпочитаю потом самостоятельно вставлять эти NOP'ы, чтобы знать, где у нас "не очень гладко". И вот тут можно его заменить чем-то более полезным:

	Acc		[SP+1]		;Acc = x, т.е координата обнаруженной точки
	SUB		[X+2j+k]	;вычитаем X, т.е Acc = x - X - разность между обнаруженной точкой и центром левого пятна
	DIV2A		[X+1]		;прибавили D/2, получаем Acc = x-X+D/2 
	[X+1]		Acc		;обновили диаметр левого пятна.
	Acc		1
	;теперь подкорректировать X-координату
	ADD		[SP+1]		;берём координату обнаруженной точки
	DIV2S		[X+1]		;вычитаем половинку диаметра
	[X+2j+k]	Acc


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

Давайте попробуем запустить хоть так - по логике вещей, оно по крайней мере должно успешно дойти до конца кадра.

Компилируется в 255 слов кода, забавно, но ещё 1 слово есть про запас :) Ну, при разрядности 8, так-то памяти и побольше есть пока что, хоть мне и хочется ВСЁ ЦЕЛИКОМ уместить в 5 килобайт...


Нет, факир был пьян. Теперь "переполнение результатов GPU", причём ещё раньше, и офигительный набор точек:

(342;197) с радиусом 3,
(348;196) с радиусом 4, и
(355;195) с радиусом -1 (!)


Ну ладно, завтра надо будет ещё громко подумать.
Tags: ПЛИС, программки, работа, странные девайсы
Subscribe

  • Формулы приведения, что б их... (и atan на ТРЁХ умножениях)

    Формулу арктангенса на 4 умножениях ещё немножко оптимизировал с помощью алгоритма Ремеза: Ошибка уменьшилась с 4,9 до 4,65 угловой секунды, и…

  • Алгоритм Ремеза в экселе

    Вот и до него руки дошли, причина станет ясна в следующем посте. Изучать чужие библиотеки было лениво (в том же BOOSTе сам чёрт ногу сломит), писать…

  • atan на ЧЕТЫРЁХ умножениях

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

  • Ай да Пафнутий Львович!

    Решил ещё немного поковыряться со своим арктангенсом. Хотел применить алгоритм Ремеза, но начал с узлов Чебышёва. И для начала со своего "линейного…

  • atan(y/x) на двух умножениях!

    Чего-то никак меня не отпустит эта тема, всё кажется, что есть очень простой и эффективный метод, надо только его найти! Сейчас вот такое…

  • Таблица коэффициентов для atan1

    Пора уже добить этот несчастный арктангенс, что-то слишком долго его ковыряю. Мы упоминали, что в оперативной памяти будет лежать таблица в 15 слов:…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments