Это заявка на победу :)) Для массива 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. премию делим на четверых уже :))