ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
28 марта
1072613 Топик полностью
Adept (27.01.2021 16:19 - 12.02.2021 14:37, просмотров: 793) ответил Adept на ОК, поделите пополам с ILYAUL :), сорри, уж больно Вы невнятно высказались. Я только сейчас понял что Вы имели ввиду. Особенно сбивало с толку "записывать туда что-нибудь по этому индексу" :))
Это заявка на победу :)) Для массива 2K имеем среднестатистически 3,5 такта на байт :)) С использованием наработок ILYAUL/SciFi и по мотивам, навеянным идеями arhiv6 

раздул цикл до 256 линейных операций "приведения к 256", потом сравниваю границы массива по старшему байту (с дискретностью 256)

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

Для 2K массива, если в финальном переборе найдём максимум сразу, то 3 такта на байт, если придётся перелопатить все 256 значений, то 4 такта на байт.

всё честно прокручено в отладчике :)

В среднем получается 3,5 такта на байт, (xmega@32MHz = 8.76МБайт/сек :))

круто ! :)


да, немного растянуто по размерам. Разменяли компактность на быстродействие, но не критично, и слегка напоминает несуразного уродца с длинными ногами, но зато он "бежит быстрее всех" пока :))


;Поиск максимального значения в блоке данных 2K, предварительно размещённом в ОЗУ
;12/II.2021
;
/*
ld - грузит в YL значение очередного байта, а st - пишет это значение в выходной массив 256 байт, причём значение является и индексом элемента массива.
Когда весь входной массив перебрали и "привели к 256", в финале просматриваем выходной 256 байт сверху вниз до первого ненулевого значения, которое и будет максимумом.

Для увеличения скорости, чтобы не контролировать выход из цикла в каждой итерации, цикл не побайтовый, а линейными кусками по 256 байт,

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

Если принципиально нужно возможность гарантированного досрочного выхода, то есть вариант с побайтовой тупой сравнилкой, но он в 2 с лишним раза более медленный :)
*/

#define	InputDataSize		2048		;размер входного массива данных
#define	InputDataLocation	0x2500		;адрес расположения  входного массива данных 
						; (массив исходных должен быть ВЫРОВНЕН в адресном пространстве кратно 256 байт)

	LDX InputDataLocation			;определим адрес расположения входного массива данных
	LDY InputDataLocation+InputDataSize	;адрес расположения выходного массива 256 байт
	LDZ InputDataLocation+InputDataSize	;определим здесь заранее (чтобы сэкономить в цикле) границу окончания массива входных данных//модификация алгоритма "приведения к 256" - "прореживанием и "растяжкой цикла"
//в зависимости от того сразу, или конце перебора в "FindMax256" встретится максимум, время выполнения для блока 2К = 6197/8231 тактов, соответственно

MainCopyCYCLE: 	//тело большого цикла из линейки 256 операций "приведения к 256" (3 такта на байт)
	ld	YL,X+		; - в данном цикле 256 таких операций "ld/st"
	st	Y,YL 
	;
	;	.
	;	.
	;	.
	;
	cp	XL,ZL		;сравнение с границей массива (дошли ли до конца)
	cpc	XH,ZH		;Если не дошли до конца, 
	brcs	mostIndexByte	;  то продолжаем цикл чтения/сравнения
	rjmp	FindMax256	;  иначе считаем, что закончили и нужно искать максимальный индекс в выходном массиве 256 байт
mostIndexByte:
	ld	TMP,InputDataLocation+InputDataSize+256 ;Проверим, не было ли в этой порции просмотренных 256 байт, максимально возможного значения 255 ?
							; (смотрим последний байт выходной таблицы) 
	cpi	TMP,255		;  Если уже встречалось максимально возможное значение (255), 
	breq	BREAK_		;    то досрочно выходим, 
	rjmp	MainCopyCYCLE	;    иначе, "шерстим" массив данных далее
	;
FindMax256://поиск первого ненулевого значения "сверху" в массиве 256 байт 
	//  в наихудшем случае, при переборе всех 256 байт время выполнения = 2048 тактов
	ser	XL		;массив должен быть выровнен в адресном пространстве кратно 256 байт
	clr	YL		;ноль для сравнения
FindMaxCycle: 
	ld	TMP,-X		;читаем очередной байт массива 
	cpse	TMP,YL		;если 0 
	rjmp	BREAK_		;как только нашли ненулевой байт - выходим 
	cpse	XL,YL		;сравнение с границей массива (дошли ли до конца)
	rjmp	FindMaxCycle	; то продолжаем цикл чтения/сравнения 
BREAK_:
	STOP			;результат (максимум) - в "TMP", нулевое значение - признак, что весь массив входных данных был нулевым

-----------------
.macro	STOP
	rjmp	PC		;Всё, стоим!!
.endmacro

P.S. премию делим на четверых уже :))

...делать нужно так, как нужно. А как ненужно - делать не нужно (С) Винни-Пух :)