Обсуждаем контроллеры компании Atmel.
Ответить

Re: Как записать код лаконичнее

Вс окт 30, 2022 12:25:57

Да нет, просто использует более выгодный по скорости порядок и состав инструкций.

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

Re: Как записать код лаконичнее

Вс окт 30, 2022 12:37:16

А кто мне мешает этот же "более выгодный по скорости порядок и состав инструкций" расписать на асме во вставке?
Никто не мешает, но в данном случае вы этого не сделали. Результат компилятора с -O3 быстрее оказался.

В данном случае компилятор применил разворачивание цикла. Команд больше, а выполняются быстрее. Есть и другие методы оптимизации. А главное, достаточно поменять ключ оптимизации и не надо переписывать вставку.

Re: Как записать код лаконичнее

Вс окт 30, 2022 12:54:48

Я бы сделал, но это не особо занимало. Ничего бы разворачивать не стал, разместил бы один, по крайней мере, массив на грани 256-байтного сегмента (ведь сказано было - это возможно), и парметром цикла был бы ZL, не проверяя ZН и не используя отдельный счётчик. Было бы, как минимум, не медленнее. Но мне лень что-то доказывать, в чём я сам уверен.
Код:
     LDI   ZL,low(Array1)
      LDI   ZH,highArray1)
      LDI   YL,low(Array2)
      LDI   YH,high(Array2)
lab: ld R16,z+
      ld  R1,y+
      sub R16.R1
      brne out_cycle
      cpi   ZL,low(Array1+40)
      brlo  lab
out_cycle: tst R16  ; вот сюда мы придём с 0 в R16 , если массивы совпали  :))

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

Re: Как записать код лаконичнее

Вс окт 30, 2022 13:36:20

Но самый быстрый способ, конечно, это был бы (как это сделал один в этом топике :) )
Дошло? :) Лаконичный код ТС быстрее вашей вставки и выполняется за 6 тактов на один элемент массива! :)))

Продолжаем ржать над ТС?

Re: Как записать код лаконичнее

Вс окт 30, 2022 14:29:39

Зачем? Ему виднее - скорость или компактность нужна. Но никак не вяжется с заглавием темы:
Как записать код лаконичнее

Может, под этим словом он подразумевает "быстрее" ? Мой телепатор перегрелся, пойду кваску хлебну. :?

СпойлерВ разделе юмора "Литературки" когда-то ( в прошлом веке ) было: "Выразитесь несколько раз лаконически (без ущерба для себя) " :)

Re: Как записать код лаконичнее

Вс окт 30, 2022 15:21:50

MLX90640 писал(а):Ну а топикстартер конечно же всех просто уделал, применив свой, наиболее "лаконичный" способ :))) Вот, "учитесь"!
А asm его ни кто не глянул?
Его asm с оптимизацией -Os соответствует asm VladislavS с -O3, один в один, и по быстродействию выходит так же 51мкс. Другая проблема - полученный в результате размер кода.

Re: Как записать код лаконичнее

Вс окт 30, 2022 16:48:41

Беда в том, что если ТС не знает как использовать цикл, то вызвать функцию с аргументами и подавно.(

Re: Как записать код лаконичнее

Вс окт 30, 2022 21:02:22

ТС использует то, что ему понятно, а не то, что вы тут ему нахимичили.

Кстати код VladislavS можно и под -Os собрать
Спойлер
Код:
uint8_t arr1[8] = {1,2,3,4,5,6,7,8};
uint8_t arr2[8] = {1,2,3,4,5,6,7,9};
uint8_t result=0;

inline uint8_t my_memcmp(uint8_t* buf1, uint8_t* buf2, uint8_t count) __attribute__((always_inline));

#pragma GCC push_options
#pragma GCC optimize ("O3")
inline uint8_t my_memcmp(uint8_t* buf1, uint8_t* buf2, uint8_t count)
{
  while(count--)     
  {
    if(*buf1++ != *buf2++) return 1;
  }
  return 0;
}
#pragma GCC push_options

int main()
 {
   result = my_memcmp(arr1,arr2,8);
   for (;;);
 }

Re: Как записать код лаконичнее

Вт ноя 01, 2022 00:35:53

Код:
uint8_t arr1[8] = {1,2,3,4,5,6,7,8};
uint8_t arr2[8] = {1,2,3,4,5,6,7,9};
uint8_t result=0;


В теме про оптимизации и производительность кода, зачем-то объявлены глобальные переменные да еще и с external linkage (!). То есть явным образом подавлены оптимизационные возможности компилятора. В данном случае это, возможно, ни на что не повлияло, но тем не менее.

Добавляем `static` и

Код:
main:
.L2:
        rjmp .L2


Совсем другое дело! Такой лаконичности никто пока продемонстрировать не смог :)

А если серьезно, то кто знает какие еще оптимизации были подавлены вашим использованием переменных с external linkage? Хотите тестировать оптимизационные возможности компилятора - не давайте ему полностью выкинуть всю функциональность (напр. `static volatile uint8_t result=0;`), но ни о каких переменных с external linkage речь быть не может. Как не может идти речи ни о каком программирования на С без массивного использования `const` и `restrict`.

Кстати, несмотря на то, что GCC - самый слабый компилятор из "большой тройки", меня сильно удивило то, что он в таком случае не не догадывается выполнить сравнение на стадии компиляции. Clang догадался.

Re: Как записать код лаконичнее

Вт ноя 01, 2022 07:02:49

Во-первых, тема отнюдь не про "оптимизацию производительности", вы невнимательно её читали.

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

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

Re: Как записать код лаконичнее

Вт ноя 01, 2022 21:29:45

KorbenDallas, хорошо, давайте массивы заставим поработать
1 код
Спойлер
Код:
volatile uint8_t arr1[8] = {1,2,3,4,5,6,7,8};
volatile uint8_t arr2[8] = {1,2,3,4,5,6,7,9};
volatile uint8_t result=0;

inline uint8_t my_memcmp(volatile uint8_t* buf1, volatile uint8_t* buf2, uint8_t count) __attribute__((always_inline));

inline uint8_t my_memcmp(volatile uint8_t* buf1, volatile uint8_t* buf2, uint8_t count)
{
  while(count--)     
  {
    if(*buf1++ != *buf2++) return 1;
  }
  return 0;
}

int main()
 {


while (1)
  {     
   result = my_memcmp(arr1,arr2,8);
   
   arr1[0]++; arr1[1]++; arr1[2]++; arr1[3]++; arr1[4]++; arr1[5]++; arr1[6]++; arr1[7]++; 
   arr2[0]++; arr2[1]++; arr2[2]++; arr2[3]++; arr2[4]++; arr2[5]++; arr2[6]++; arr2[7]++; 
  }

 }
Так сойдет?

На -Os 141мкс 320байт
на -O3 55мкс 388байт
2 код
Спойлер
Код:
volatile char x1[8] = {1, 2, 3, 4, 5, 6, 7, 8};
volatile char x2[8] = {1, 2, 3, 4, 5, 6, 7, 9};
volatile uint8_t result=0;

int main(){

while (1)
  {
   if((x1[0] == x2[0])
      &&(x1[1] == x2[1])
      &&(x1[2] == x2[2])
      &&(x1[3] == x2[3])
      &&(x1[4] == x2[4])
      &&(x1[5] == x2[5])
      &&(x1[6] == x2[6])
      &&(x1[7] == x2[7])
   ) result=0;
   else result=1;

   x1[0]++; x1[1]++; x1[2]++; x1[3]++; x1[4]++; x1[5]++; x1[6]++; x1[7]++; 
   x2[0]++; x2[1]++; x2[2]++; x2[3]++; x2[4]++; x2[5]++; x2[6]++; x2[7]++; 
   
   }

}
На -Os и -O3 asm-код одинаковый, 53мкс 384байт
:tea:
Ответить