Например TDA7294

Форум РадиоКот • Просмотр темы - Хитрые, необычные алгоритмы и код
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Сб дек 27, 2025 18:07:01

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 414 ]     ... , , , 16, , , ...  
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вс ноя 03, 2024 13:33:13 
Мучитель микросхем

Карма: 1
Рейтинг сообщений: 48
Зарегистрирован: Вт окт 01, 2024 15:22:33
Сообщений: 478
Рейтинг сообщения: 0
Будет много. Это лишь вопрос времени. Главное, что эти расширения документированы и для них есть кодогенерация.

Возьмем, для пример, STM32, там до сих STM32F1 нарасхват, а это у них первая серия среди кортексов. После того были F0/F2/F3/F4/F7/G0/G4/C0/L0/L1/L4/L4+/L5/U0/U5/H5/H7, на подходе U3 и N6. Helium есть только у последнего и это нишевый продукт с пиковой производительностью и NPU, даже через 5 лет после его выхода на один проданный N6 будут приходиться сотни мк других серий. Возможно вы удивитесь, но даже на самых простых из этих мк, где даже деления нет, не то что FPU, тоже медианы высчитывают и производительность там нужна сейчас, а не приблизительно никогда )

ПростоНуб писал(а):
LLVM уже года четыре, как поддерживает RVV.

Покажите мне живой мк на RISC-V с RVV )

ПростоНуб писал(а):
Но всё же, где в моем коде нахождения медианы Вы обнаружили хоть какую-то зависимость от Cortex-M или RISC-V?
Почему Вы упорно отказываетесь считать этот код универсальным для любого микропроцессора, от i4004 до AMD EPYC 9965?

А я не отказываюсь. Вопрос даже не в том какой вариант кода лучше, просто мой пузырьковый вариант, который я написал чисто ради интереса, показывает схожую производительность или даже чуть лучше. Это эмпирический факт, вы не можете его опровергнуть, у вас даже мк нужного нет для тестов. Зато можно дисквалифицировать сам мк, как устаревший, и вы снова на коне )


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вс ноя 03, 2024 14:54:53 
Собутыльник Кота
Аватар пользователя

Карма: 38
Рейтинг сообщений: 268
Зарегистрирован: Пт сен 07, 2018 20:20:02
Сообщений: 2723
Откуда: деревня в Тульской губернии
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
Возьмем, для пример, STM32

На STM32 свет клином сошелся?

Покажите мне живой мк на RISC-V с RVV )


Ну если именно "показать", то вот например:


ПростоНуб писал(а):
Но всё же, где в моем коде нахождения медианы Вы обнаружили хоть какую-то зависимость от Cortex-M или RISC-V?
Почему Вы упорно отказываетесь считать этот код универсальным для любого микропроцессора, от i4004 до AMD EPYC 9965?

А я не отказываюсь.


Именно, что отказываетесь, упорно применяя код на Cortex-M33, игнорируя всё остальное.
Выше, например, Вы захотели увидеть именно MCU и именно RISC-V с поддержкой векторных инструкций.
Как будто этот код нельзя использовать на одноплатниках с тем же Allwinner Xuantie-C906.
Это даже не считая того, что похожий код я сейчас использую на AMD EPIC 9374F.

Я вот подумал, попробуем начать с начала. Давайте обсудим первое мое утверждение, а потом будем двигаться дальше.
"Известными сейчас векторными расширениями систем команд, вне зависимости от архитектуры или конкретного процессора, сравнения векторизуется, а вот перестановки (swap) - нет."
Есть возражения?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вс ноя 03, 2024 18:15:49 
Мучитель микросхем

Карма: 1
Рейтинг сообщений: 48
Зарегистрирован: Вт окт 01, 2024 15:22:33
Сообщений: 478
Рейтинг сообщения: 0
На STM32 свет клином сошелся?

Популярные и довольно дешевые мк, почему нет? Что принципиально поменяется, если взять мк другого производителя? У ESP32 один S3 с SIMD, у Renesas - один RA8...

ПростоНуб писал(а):
Ну если именно "показать", то вот например:

2 ядра, 64 бита, 1.6GHz, флеша нет, 512MB DDR, MMU - это, по вашему, микроконтроллер? Такой же SoC, как Raspberry Pi, только там Cortex-A. Но ок, по крайней мере это действительно китайский RISC-V с RVV, возможно единственный )

ПростоНуб писал(а):
Именно, что отказываетесь, упорно применяя код на Cortex-M33, игнорируя всё остальное.
Выше, например, Вы захотели увидеть именно MCU и именно RISC-V с поддержкой векторных инструкций.
Как будто этот код нельзя использовать на одноплатниках с тем же Allwinner Xuantie-C906.
Это даже не считая того, что похожий код я сейчас использую на AMD EPIC 9374F.

Я упорно применяю код на все кортексы с которыми имел дело, от M0 до M33, и RISC-V, хотя тут я не фанат. Вы сами применяете, собственно началось все со слов о том, что у вас медианный фильтр работает на ESP32-C3. RV32IMC - это же вообще примитивное ядро, ни FPU, ни даже Atomic memory. Бледная тень M33, но вам нормально и производительности хватает без SIMD ) Кстати, в CMSIS-DSP все на интринсиках написано, а не оставлено на откуп компилятору, так что даже имея Helium код может совсем другой получиться.

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

Без понятия, у меня только gcc для x86 с Compiler Explorer сгенерил компактный SIMD код для вашего варианта, похуже для моего, clang мимо, оба компилятора для ARM тоже мимо, в Visual Studio с родным компилятором никаких SIMD не видно длаже если AVX512 включить...


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вс ноя 03, 2024 19:48:02 
Собутыльник Кота
Аватар пользователя

Карма: 38
Рейтинг сообщений: 268
Зарегистрирован: Пт сен 07, 2018 20:20:02
Сообщений: 2723
Откуда: деревня в Тульской губернии
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
ПростоНуб писал(а):
"Известными сейчас векторными расширениями систем команд, вне зависимости от архитектуры или конкретного процессора, сравнения векторизуется, а вот перестановки (swap) - нет."

Без понятия

Вот на этом можно пока финишировать. Обсуждать выгоды векторизации с оппонентом, который даже не хочет ничего о векторизации знать, действительно бессмысленно.


Вернуться наверх
 
Эиком - электронные компоненты и радиодетали
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вт дек 03, 2024 14:39:43 
Первый раз сказал Мяу!

Зарегистрирован: Пн мар 18, 2024 22:04:17
Сообщений: 37
Рейтинг сообщения: 4
Тоже свой алгоритм нахождения медианы... точнее среднего от медиан массива (отсекается по 0, 1 или несколько крайних значений, а из остального находится среднее арифметическое), сам массив при этом не повреждается. Условие - числа в массиве менее половины емкости типа переменной, т.к. старший бит отдаётся под метку... алгоритм разрабатывался для обработки данных с АЦП - там это условие соблюдается.
Фильтр не портит массив, это позволяет, используя колцевой буфер, использовать результаты работы АЦП повторно (это значит, что результаты фильтрации можно получать с частотой опроса АЦП)
К сожалению исходный алгоритм фильтра остался на жетком диске дома... а это я из готового кода "быстрого АмперВольтВаттОмМетра для ЛБП на меге8" выкусил.
СпойлерКод написан в кодевижене, прошу понять и простить :))
Код:
unsigned int filtr (unsigned int inp[], unsigned char Length, unsigned char Median){
//inp[]  массив входных данных
//Length длина массива входных данных
//Median количество отбрасываемых крайних элементов с каждой стороны, т.е. мощность медианного фильтра
unsigned int tmp;
unsigned char i,j,k,u;         //счетчики и ограничители
unsigned long summ = 0;        //аккумулятор для суммирования усредняемых элементов массива
k=Length-Median;               //количество итераций поиска
u=k-Median;                    //определяем, сколько элементов нужно усреднять
while (k) {
          tmp=~(1<<15);        //0x7FFF - максимально допустимое для алгоритма число
          i=Length;
          while (i>0)          //в цикле перебираем весь массив - ищем минимальный элемент
              {
              i--;
              if (tmp >= inp[i])
                  {
                  j = i;
                  tmp = inp[i];
                  };
              };
          if (k<=u) summ+=tmp; //складываем в аккумулятор если обработать осталось <= требуемое для усреднения количество элементов
          inp[j]|=(1<<15);     //ставим метку на найденном и обработанном элементе, с ней он уже не будет минимальным
          k--;
          };
//----------
k=Length;                      //убираем все метки
do {inp[--k]&=~(1<<15);}
while (k>0);
//----------
tmp=summ/u;                    //находим среднее арифметическое
return (tmp);                  //и возвращаем его
}
Да, этот код не будет минимальным в вашей гонке, но у него задача и возможности другие - он позволяет быстро обрабатывать и выводить данные с относительно медленного (т.к. там производится серия измерений для уменьшения дискретности и шага отображения) АЦП.
Вроде всё верно выкусил, там просто ещё автокалибровка и автоподстройка 0 и сохранение этих данных в сжатом виде в служебной области массива реализованы... были...

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

ПС не уверен, что я до среднего уровня тут присутствующих дотягиваюсь, т.к. смотрю, все уже на STMах и ESPхах катаются... а я с ними только в среде ардуино дело имел... :roll:


а кто гарантирует, что
Код:
Length
будет как минимум в два раза больше
Код:
Median
-- поскольку иначе будет UB (неопределенное поведение).

Код:
tmp=~(1<<15);        //0x7FFF - максимально допустимое для алгоритма число
-- почему бы тут просто не сделать
Код:
tmp=0x7FFF;
?

так же если никогда не выполнится
Код:
if (tmp >= inp[i])
                  {
                  j = i;
                  tmp = inp[i];
                  };

то будет снова UB -- поскольку
Код:
 inp[j]|=(1<<15);
обратится к неинициализированной переменной.

Код:
tmp=summ/u;                    //находим среднее арифметическое
return (tmp);                  //и возвращаем его
-- тут можно просто сделать
Код:
return summ / u;


Добавлено after 16 minutes 8 seconds:
ПростоНуб, ловите пузырьковую и не ворованную у вас median5 ) Алгоритм простейший: тремя перестановками передвигаем в конец наибольшее из 4-х значений, оно нам больше не нужно, то же самое повторяем для оставшихся четырех, осталось 3 значения из которых наибольшее и будет искомым. 1000 итераций для O3 выполняются за 31029 и 27050 тактов в мою пользу, с O2 вы выигрываете 33 такта )

Не вижу. Полностью профилирующий код опять ведь не привели.
А я привожу:
Спойлер
Код:
#include <algorithm>
#include <cstdint>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define BUF_SIZE 400000*77
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define SWAP(a,b,type) {type ttttttttt=a;a=b;b=ttttttttt;}

int median5_adrift(int* arr)
{
   int a = arr[0], b = arr[1], c = arr[2], d = arr[3], e = arr[4];

   if (a > b) std::swap(a, b);
   if (b > c) std::swap(b, c);
   if (c > d) std::swap(c, d);
   if (a > b) std::swap(a, b);
   if (b > c) std::swap(b, c);
   if (c > e) std::swap(c, e);
   if (a > b) std::swap(a, b);
   return (b > c) ? b : c;
}

int median3 (int a, int b, int c) {
  return MAX(MIN(a,b),MIN(c,MAX(a,b)));
}

int median5 (int *v) {
  return median3(
        v[4],
        MAX(MIN(v[0], v[1]), MIN(v[2], v[3])),
        MIN(MAX(v[0], v[1]), MAX(v[2], v[3]))
    );
}

void do_only_mean(int *rand_buf, int *res_buf) {
  for (int i = 0; i < BUF_SIZE - 5; i++) {
    res_buf[i] = median5(rand_buf++);
  }
  return;
}

void adrift_do_only_mean(int *rand_buf, int *res_buf) {
  for (int i = 0; i < BUF_SIZE - 5; i++) {
    res_buf[i] = median5_adrift(rand_buf++);
  }
  return;
}

int main() {
  int *rand_buf = (int*) malloc(BUF_SIZE*sizeof(int));
  int *res_buf = (int*) malloc(BUF_SIZE*sizeof(int));

  srand(time(NULL));
  for ( int i = 0; i < BUF_SIZE; i++) {
    rand_buf[i] = rand();
  }

  clock_t start = clock() ;
  adrift_do_only_mean(rand_buf, res_buf);
  clock_t end = clock() ;
  double adrift_elapsed_time = (end - start) / (double)CLOCKS_PER_SEC;

  start = clock() ;
  do_only_mean(rand_buf, res_buf);
  end = clock() ;
  double mean_elapsed_time = (end - start) / (double)CLOCKS_PER_SEC;

  printf("%f -- %f => %f\n", adrift_elapsed_time, mean_elapsed_time, adrift_elapsed_time / mean_elapsed_time);
}


Без оптимизации мой код выигрывает в 2 раза (gcc ./median.cpp)
1.701809 -- 0.775227 => 2.195240
С оптимизацией в 3.5 раза (gcc -O3 ./median.cpp)
0.116901 -- 0.032853 => 3.558305

На самом деле, это давно известно, что std::swap не векторизуется. Ну хоть убейся. А сравнения - легко и просто.
Если заинлайнить median3(), то median5() будет всего 16 команд.
Спойлер
Код:
   vmovd   (%rdi), %xmm2
   vmovd   4(%rdi), %xmm4
   vmovd   8(%rdi), %xmm0
   vpminsd   %xmm4, %xmm2, %xmm1
   vmovd   12(%rdi), %xmm5
   vpminsd   %xmm5, %xmm0, %xmm3
   vpmaxsd   %xmm4, %xmm2, %xmm2
   vpmaxsd   %xmm5, %xmm0, %xmm0
   vpmaxsd   %xmm1, %xmm3, %xmm3
   vpminsd   %xmm2, %xmm0, %xmm0
   vmovd   16(%rdi), %xmm1
   vpmaxsd   %xmm3, %xmm1, %xmm2
   vpminsd   %xmm3, %xmm1, %xmm1
   vpminsd   %xmm2, %xmm0, %xmm0
   vpmaxsd   %xmm1, %xmm0, %xmm0
   vmovd   %xmm0, %eax
   ret

А портянку median5_adrift() остается на регистрах общего назначения из 34 команд
Спойлер
Код:
   movl   (%rdi), %r8d
   movl   4(%rdi), %edx
   movl   8(%rdi), %eax
   movl   12(%rdi), %ecx
   movl   16(%rdi), %esi
   cmpl   %edx, %r8d
   jg   .L2
   cmpl   %eax, %edx
   jle   .L8
   movl   %edx, %edi
   movl   %r8d, %edx
   movl   %edi, %r8d
.L3:
   cmpl   %r8d, %ecx
   movl   %eax, %edi
   cmovg   %r8d, %ecx
   cmpl   %edx, %eax
   cmovge   %edx, %eax
   cmovge   %edi, %edx
.L4:
   cmpl   %ecx, %edx
   movl   %ecx, %edi
   cmovle   %edx, %ecx
   cmovle   %edi, %edx
   cmpl   %ecx, %eax
   cmovl   %ecx, %eax
   cmpl   %edx, %esi
   cmovle   %esi, %edx
   cmpl   %edx, %eax
   cmovl   %edx, %eax
   ret
   .p2align 4
   .p2align 3
.L2:
   cmpl   %eax, %r8d
   jg   .L3
   cmpl   %ecx, %eax
   cmovle   %eax, %ecx
   movl   %edx, %eax
   movl   %r8d, %edx
   jmp   .L4


Предвидя возражения, что используете легаси архитектуру без поддержки векторизации, предложу подумать, а что будет, когда потребуется сменить МК на более современный. Переписывать код будете?

Добавлено after 32 minutes 29 seconds:
Что я вижу вокруг себя? Берут программиста-новичка, выпускника бакалавриата. И ставят задачу: мы тут 20 лет используем вот такую систему программирования - ХХХХХ - слыхал? Не слыхал? Ну ничего, разберешься. Надо, чтобы ты завтра на ней сделал сервер ИИ. Посмотри, как мы 20 лет делали сервер БД, и сделай по образцу. Сдаём через месяц. Справишься?

В итоге этот новичок, если не сбегает, выпучив глаза копипастит код из прежних проектов, ни на секунду не задумываясь, как оно устроено, иначе в сроки не уложиться. И если оно потом заработает (а рано или поздно заработает), оно становится
частью той самой базы "мы 20 лет". В итоге после года работы профессиональный рост такого программиста равен 0, но от реальности он отстал почти на бесконечность.

А можно уточнить, в каких системных интеграторах или IT компаниях Вы такое видите?
Вот я не вижу. Если берем стажера после бакалавриата, то в более-менее свободное плавание он допускается только через полгода, не ранее. И все отдают отчет, что в течении этого полугода такой джун - убыточен. Каждая строчка его кода проходит очень жесткий code review и его PR сливается с основной веткой, порой, чуть ли не с десятой попытки. Уж простите, но утверждать PR моя прямая задача, как лида. Поэтому знаю о чем пишу.

Именно поэтому и прибегает к ИИ-генераторам кода.

Я же выше написал, как используются ИИ в профессиональной разработке. Если и находится разработчик, доверяющий AI, то он или очень быстро перестанет ему доверять, или я с ним расстанусь.

Программист делает так код

Прежде чем писать код, сначала надо осмыслить постановку, найти в ней ошибки, противоречия и неоднозначности, устранить их все вместе с аналитиком и заказчикам. И именно в этом заключается львиная часть работы разработчика.

Чтобы это говнище ворочалось, выпускаются более мощные процессоры. Более мощные процессоры порождают желание наговнокодить то, что вчера считалось невозможным... И круг замыкается.

Не для этого они выпускаются, а для того, чтобы можно было решать задачи, которые еще лет 10 назад были доступны только суперкомпьютерам, да и то не всем.
А уж кто и как свою дурь и лень при этом проявляет - отдельная тема и явно уже вне данного топика.

В общем, кризис жанра полный

Опять видите только осколки вершины айсберга, да и то, выборочно. А ведь, если говорить об МК, то Espressif фактически совершил революцию своими дешевыми МК с WiFi и BLE.

Недавно впервые зашел на сайт известного Алекса Гайвера... Увидел там проект вентилятора, который нацеливается на лицо методом распознавания лица на видео. Еще вчера это было невозможно, теперь с этим справился самодельщик. И? Ни один человек в мире не будет пользоваться таким вентилятором иначе, как хвастаясь перед другими.

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



Код:
   if (a > b) std::swap(a, b);
   if (b > c) std::swap(b, c);
   if (c > d) std::swap(c, d);
   if (a > b) std::swap(a, b);
   if (b > c) std::swap(b, c);
   if (c > e) std::swap(c, e);
   if (a > b) std::swap(a, b);
-- а это разве не
Цитата:
std::sort
? и после можно просто
Код:
return arr[2];

тут вообще просто можно сделать
Цитата:
std::nth_element
и после тот же элемент возвращать получается, который и указан как
Цитата:
nth



Код:
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define SWAP(a,b,type) {type ttttttttt=a;a=b;b=ttttttttt;}
-- так же не понятно зачем это было привнесено -- есть же
Цитата:
std::*
такие функциональности...

Код:
  int *rand_buf = (int*) malloc(BUF_SIZE*sizeof(int));
  int *res_buf = (int*) malloc(BUF_SIZE*sizeof(int));
-- такое надо заменить на
Цитата:
std::vector<int>(BUF_SIZE)


Цитата:
Если заинлайнить median3(), то median5() будет всего 16 команд.
-- различные инструкции потребляют различное количество времени работы ЦПУ -- по этому по количеству команд нельзя судить о быстродействии. Более того следует учитывать, что в каком то другом компиляторе будет сгенерирован другой ассемблер (в том числе при других опциях компиляции).

Код:
int median5_adrift(int* arr)
-- ну и могу рекомендовать заменить такое везде на
Цитата:
std::span
или если нужна гарантированная длина массива на
Цитата:
std::array


а вообще если доступен c++20 -- можно удобно использовать
Цитата:
std::ranges::take_view
как входной аргумент с указыванием количества элементов. -- или так не получится как я хочу... хммм...

тогда можно точно указывать в std::span вторым аргументом шаблона фиксированный размер (вместо умолчательного динамического).


Последний раз редактировалось safocl Вт дек 03, 2024 15:32:14, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вт дек 03, 2024 15:30:08 
Друг Кота
Аватар пользователя

Карма: 52
Рейтинг сообщений: 2114
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Сообщений: 7059
Откуда: Сердце Пармы
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (2)
safocl, :beer:
1) Length>2*Median
да, у меня это на совести программиста, делалось для маленького проекта... действительно, стоит добавить проверку...
2) tmp=~(1<<15);
это борьба с магическими числами..., компилятор всё равно в 0x7FFF сам пересчитает
3) j = i;
да, пожалуй стоит какой то брейкпоинт на это поставить... чтобы в случае чего ошибку сразу видно стало
4) return...
на самом деле у меня в выдоде немного по другому сделано (для увеличения разрядности выходного числа за счет множества измерений), так написал для понятности... но сделано по очереди... сейчас не помню, вроде тогда пару байт флеша я этим сэкономил...

_________________
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вт дек 03, 2024 15:37:10 
Первый раз сказал Мяу!

Зарегистрирован: Пн мар 18, 2024 22:04:17
Сообщений: 37
Рейтинг сообщения: 0
safocl, :beer:
1) Length>2*Median
да, у меня это на совести программиста, делалось для маленького проекта... действительно, стоит добавить проверку...
2) tmp=~(1<<15);
это борьба с магическими числами..., компилятор всё равно в 0x7FFF сам пересчитает
3) j = i;
да, пожалуй стоит какой то брейкпоинт на это поставить... чтобы в случае чего ошибку сразу видно стало
4) return...
на самом деле у меня в выдоде немного по другому сделано (для увеличения разрядности выходного числа за счет множества измерений), так написал для понятности... но сделано по очереди... сейчас не помню, вроде тогда пару байт флеша я этим сэкономил...

2) что-то не особо получилось честно говоря -- никак магическое число не ушло -- да и неважно оно по сути, поскольку не участвует в каком либо интерфейсе.
4) в c++ есть RVO, которое гарантирует, что надо налету подставить результат выражения под
Цитата:
return
на место вызова функции. без каких либо дополнительных копирований. а так тут получается, что записывается кудато сначала, и после из нее вычисляется выражение (круглые скобки), которое равно значению в этой переменной.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вт дек 03, 2024 15:46:46 
Мучитель микросхем

Карма: 1
Рейтинг сообщений: 48
Зарегистрирован: Вт окт 01, 2024 15:22:33
Сообщений: 478
Рейтинг сообщения: 0
Код:
   if (a > b) std::swap(a, b);
   if (b > c) std::swap(b, c);
   if (c > d) std::swap(c, d);
   if (a > b) std::swap(a, b);
   if (b > c) std::swap(b, c);
   if (c > e) std::swap(c, e);
   if (a > b) std::swap(a, b);
-- а это разве не
Цитата:
std::sort
? и после можно просто
Код:
return arr[2];

std::sort сортирует массив, а его портить нельзя, потому я грузил сначала в переменные.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вт дек 03, 2024 21:03:13 
Первый раз сказал Мяу!

Зарегистрирован: Пн мар 18, 2024 22:04:17
Сообщений: 37
Рейтинг сообщения: 0
Код:
   if (a > b) std::swap(a, b);
   if (b > c) std::swap(b, c);
   if (c > d) std::swap(c, d);
   if (a > b) std::swap(a, b);
   if (b > c) std::swap(b, c);
   if (c > e) std::swap(c, e);
   if (a > b) std::swap(a, b);
-- а это разве не
Цитата:
std::sort
? и после можно просто
Код:
return arr[2];

std::sort сортирует массив, а его портить нельзя, потому я грузил сначала в переменные.

зачем тогда вообще принимать какой то внешний источник памяти, если просто можно принимать управляемую память -- к примеру простой std::array ? ее можно портить как хочешь -- а главное будут работать все стандартные алгоритмы


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вт дек 03, 2024 22:29:03 
Мучитель микросхем

Карма: 1
Рейтинг сообщений: 48
Зарегистрирован: Вт окт 01, 2024 15:22:33
Сообщений: 478
Рейтинг сообщения: 0
safocl, обычный там массив, но после вычисления медианы нужно отбросить первый элемент и рассчитать вторую, а после сортировки этот первый элемент может оказаться где угодно.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вт дек 03, 2024 22:45:10 
Первый раз сказал Мяу!

Зарегистрирован: Пн мар 18, 2024 22:04:17
Сообщений: 37
Рейтинг сообщения: 0
Adrift, я имел ввиду:
Код:
int median5_adrift(std::array<int,5> values)
{
   std::nth_element( values.begin(),  values.begin() + 2, values.end() );
   return values[2];
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Вт дек 03, 2024 22:50:31 
Мучитель микросхем

Карма: 1
Рейтинг сообщений: 48
Зарегистрирован: Вт окт 01, 2024 15:22:33
Сообщений: 478
Рейтинг сообщения: 0
Там спор был о производительности, потому копирование массива не вариант.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Ср дек 04, 2024 02:19:18 
Первый раз сказал Мяу!

Зарегистрирован: Пн мар 18, 2024 22:04:17
Сообщений: 37
Рейтинг сообщения: 0
Adrift, так ты все равно выделяешь память -- только отдельными переменными на стеке -- ровно также как если поместить на стеке массив (как в моем варианте) )))
точнее так будет даже выгоднее -- поскольку придется лишь однажды по указателю прыгать в "неизвестность" -- и копировать куском, вместо нескольких мелких копирований... почти всегда второе будет медленнее


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Ср дек 04, 2024 10:19:55 
Мучитель микросхем

Карма: 1
Рейтинг сообщений: 48
Зарегистрирован: Вт окт 01, 2024 15:22:33
Сообщений: 478
Рейтинг сообщения: 0
Safocl, с оптимизацией мои переменные загрузятся из массива сразу в регистры, а вот std алгоритмы будут сортировать массив в памяти, что медленно само по себе, особенно на мк типа STM32H7, где память может работать на вдвое меньше частоте относительно CPU. Но я потестил, твой вариант медленнее в 4 раза )


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Ср дек 04, 2024 18:24:56 
Первый раз сказал Мяу!

Зарегистрирован: Пн мар 18, 2024 22:04:17
Сообщений: 37
Рейтинг сообщения: 0
Adrift, интересно кто гарантировал такую оптимизацию, почему она невозможна с моим вариантом, если они идентичны абсолютно по расположению в памяти? Откуда вообще информация, что переменные сразу появятся в регистрах без обращения к памяти? -- как раз я считаю будет происходить абсолютно обратное.
При этом не учитывается, что в случае с std::nth_element элементы не будут сортироваться полностью, а сделается только подстановка в указанный элемент значения, которое было бы при сортировке... -- тоесть иными словами такой вариант алгоритма сильно выигрывает в несколько раз относительно изначального варианта со свапами значений всех переменных (где как раз происходит полная сортировка).

Добавлено after 3 minutes 15 seconds:
Но я потестил, твой вариант медленнее в 4 раза )

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

upd. Еще могут быть странные опции компилятора...
https://godbolt.org/z/P5zErWh6z -- почему то странно при изменении оптимизации с O1 на O2 (или O3) меняются местами по громоздскости ассемблерные выводы -- с O1 получается сильно компактнее мой вариант -- вообще конечно не показатель конечно количество инструкций в ассемблере -- они могут потреблять разное время ЦПУ, но все равно просто очень странно -- возможно даже так при большем количестве инструкций оно будет работать быстрее, чем с меньшим количеством инструкций (но не факт).


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Ср дек 04, 2024 19:12:31 
Мучитель микросхем

Карма: 1
Рейтинг сообщений: 48
Зарегистрирован: Вт окт 01, 2024 15:22:33
Сообщений: 478
Рейтинг сообщения: 0
Adrift, интересно кто гарантировал такую оптимизацию, почему она невозможна с моим вариантом, если они идентичны абсолютно по расположению в памяти? Откуда вообще информация, что переменные сразу появятся в регистрах без обращения к памяти? -- как раз я считаю будет происходить абсолютно обратное.

Сам же даешь линк на Compiler Explorer, непонятно только чего для x86 ) Смотрим для M33, в моем коде в начале пара ldrd и одна ldr грузят в регистры значение из памяти, дальше работа только с регистрами. Твой код в 6 раз больше по объему и постоянно обращается к памяти.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Ср дек 04, 2024 19:24:07 
Первый раз сказал Мяу!

Зарегистрирован: Пн мар 18, 2024 22:04:17
Сообщений: 37
Рейтинг сообщения: 0
https://godbolt.org/z/EEYjeM7T6 -- все встало на свои места -- мой код успешно может оптимально инлайниться, а так же сжиматься при использовании... -- ну собственно понятно из-за чего -- указатель вообще не может нормально оптимизироваться -- в реальном случае с получением данных из dma будет еще различима разница моего кода с изначальным -- мой код будет куда более быстродейственным (даже только учитывая фактор по памяти).

Добавлено after 3 minutes 13 seconds:
и постоянно обращается к памяти.

не больше чем твой изначальный вариант -- так же напрямую мапится в стек (регистры) -- тут никакого различия вообще не может быть с обычными несколькими переменными... а вот сам факт нормального мепинга памяти в другую -- и тот фактор, что сам по себе std::array в аргументах функции после может безгранично по использованию памяти оптимизироваться решает очень сильно. Грубо говоря мой пример абсолютно идентичен случаю, если в аргументах принимать просто 5 интов.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Ср дек 04, 2024 19:29:22 
Мучитель микросхем

Карма: 1
Рейтинг сообщений: 48
Зарегистрирован: Вт окт 01, 2024 15:22:33
Сообщений: 478
Рейтинг сообщения: 0
https://godbolt.org/z/EEYjeM7T6 -- все встало на свои места -- мой код успешно может оптимально инлайниться, а так же сжиматься при использовании...

Что встало на места? Где твой код успешно оптимально заинлайнился? А это тогда что? )
Код:
callq   void std::__introselect<int*, long, __gnu_cxx::__ops::_Iter_less_iter>(int*, int*, int*, long, __gnu_cxx::__ops::_Iter_less_iter)


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Ср дек 04, 2024 19:41:13 
Первый раз сказал Мяу!

Зарегистрирован: Пн мар 18, 2024 22:04:17
Сообщений: 37
Рейтинг сообщения: 0
Adrift, как раз таки успешный инлайнинг -- вызова именно моей функции нет -- компилятор поместил все нужное в тело вызываемой функции...

А так же я всмотрелся и разрешил тот самый странный вариант при O2 оптимизации -- там на самом деле вся портянка кода принадлежит к фунцкии, которая изначальная с указателем в аргументах, а не моему варианту -- просто расположил компилятор строки когда так странно....

https://godbolt.org/z/8PcKWscP4 -- вооо -- можно попереключать #if для разных вариантов -- что бы не было вперемешку ассемблера для разных вариантов...


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Хитрые, необычные алгоритмы и код
СообщениеДобавлено: Ср дек 04, 2024 19:51:39 
Мучитель микросхем

Карма: 1
Рейтинг сообщений: 48
Зарегистрирован: Вт окт 01, 2024 15:22:33
Сообщений: 478
Рейтинг сообщения: 0
как раз таки успешный инлайнинг -- вызова именно моей функции нет -- компилятор поместил все нужное в тело вызываемой функции...

Вызов std::__introselect(__first, __nth, __last, std::__lg(__last - __first) * 2, __comp) - это, по сути, std::nth_element() и есть.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 414 ]     ... , , , 16, , , ...  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 19


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y