Pull to refresh

Comments 23

А как насчет поддержки DSP-инструкций компиляторами? В исходниках CMSIS-DSP нет явных ассемблерных команд обращения к DSP-инструкциям. На первый взгляд обычные арифметические операции. Вероятно, предполагается что компилятор их сам оптимизирует?
Интринсики там кругом. А для общего ускорения активно используется размотка циклов.
Я поясню в чем вопрос. Возьмем к примеру из исходников DSP_lib функцию arm_abs_f32() — там нет никаких специальных вызовов, кроме стандартной fabsf() из <math.h>. То же самое в arm_mult_f32() — обычная конструкция pDst++ = (pSrcA++) (pSrcB++);
На каком этапе происходит вызов FPU-инструкций?

VABS.F32 получение абсолютного значения операнда
VFMA.F32 перемножение двух переменных, прибавление результата умножения к содержимому указанного регистра
К примеру, мой проект компилируется gcc, без подключения DSP_lib. При беглом просмотре ассемблерного листинга видно, что он активно использует инструкции FPU, и иногда даже проскальзываю инструкции DSP. Но например, sqrtf() он не заменил на аппаратную реализацию. Получается, что не обязательно тянуть в проект DSP_lib, так как по большей части эти инструкции оптимизирует сам компилятор, и DSP_lib полагается на него.
В случае arm_abs_f32() полагаются на авто-векторизацию компилятора. При соблюдении некоторых условий, как то: выравнивание массивов, исключение пересечений между массивами, и т.п. это работает. Часто необходимо указать на эти условия компилятору напрямую.
В других случаях, как тот же SADD16 упомянутый в статье, команды четко прописывают через интринсики.
Вот реальный пример: STM32F303 с ядром M4F, компилятор gcc (arm-none-eabi). Использую fabsf(val) в коде — заменяется на одну инструкцию VABS.F32. Но в функциях из <math.h>, например atan2f() вызовы fabsf() ведут на софтовую реализацию. Притом что в этой фукнции ЕСТЬ другие инструкции FPU, то есть линкер подключает вроде как правильную библиотеку, заточенную под сопроцессор. Что это, недоработки реализации?
Как объясняют коллеги, стандартная библиотека намеренно собирается с -fno-builtin, чтобы не возникло циклических зависимостей — например, чтобы реализация memset() не была заменена на вызов стандартной memset().

Возможно, в будущем процесс сборки стандартной библиотеки усовершенствуют, чтобы распознавать "простые" функции внутри "сложных".
Кстати говоря, слово «cortex» переводится как «кора головного мозга» — структура, отвечающая за согласованную работу органов, мышление, высшую нервную деятельность. По-моему, прекрасное название.

Слово «cortex» переводится просто как «кора» — и применяется к коре как головного мозга, так и других внутренних органов, а также волос, растений и пр.
Ваша правда, спасибо за уточнение!)

Но если, например, вбить cortex в поиск гугла по картинкам, то чаще всего имеется в виду либо процессор, либо головной мозг человека.
Это потому, что гугл по вашей истории поиска угадывает вашу область интересов ;-)
в режиме инкогнито в выдаче ещё больше мозгов %)
UFO just landed and posted this here
Извините, конечно, но я не верю в такую криворукость разработчиков библиотечных функций. Получить на задаче FFT при переходе на аппаратную плафающую точку всего лишь 2.2 рост производительность — так не бывает. Должен быть рост на порядок, а то и выше.
С вашими аргументами сложно спорить))
Ну, не верьте, что уж там
Давайте немного посчитаем.
У Вас написано, что на индикатор выводится
количество машинных циклов за которые была исполнена функция ProcessFFT()
Поскольку мы видим число 389775 и частота 48 МГц, то время выполнения преобразования должно составить 389775/48000000*1000 = 8 мсек.
То есть показанный Вами график потребления на самом деле включает в себя 8 мсек, за которые производится вычисления и еще 49-8=41 мсек на дополнительные действия, природа которых пока остается за кадром (скорее всего, связаны с выводом на экран).

Тогда следующий показанный Вами график должен содержать в себе вычисления длиной 108-41 = 63 мсек и те же самые неизвестные действия. Сравнение двух графиков подтверждает данную гипотезу, мы видим в конце всплеска потребления идентичные плато с идентичной просадкой потребления в конце одинаковой длительности. К сожалению, второй график не сопровождается значениями на индикаторе, так что эти суждения носят оценочный характер.

Тогда ускорения вычислений составит 63/8 = 8 раз, что приблизительно соответствует моим ожиданиям об ускорении на порядок и весьма слабо коррелирует с Вашим значением 2,2 раза. Вспоминается старый анекдот "Ну да, где то так, 5-6, но никак не 17".

Если я пишу "не верю", то следует читать "мой многолетний опыт заставляет меня сомневаться" и в данном конкретном случае так и есть,
в то время как, Ваша фраза "Ну, не верьте, что уж там" должна была означать "я все перепроверил, тем не менее мои результаты верны", но на самом деле означает "мне лениво вдумываться в мои результаты, я всего-лишь правильно поделил 108/49".
Осторожнее надо быть с интерпретацией результатов экспериментов.
Нам вообще нельзя проводить эксперимент, заранее не зная результата, мы все таки не ученые, а инженеры, в противном случае результаты могут нас весьма неприятно удивить.

Ну и в заключение маленькая ремарка — Вы предупредили, что код не Ваш, что это пример от производителя, но тем не менее — опубликовали его Вы, и поэтому, хотя основная часть замечания уйдет к "индусам", маленькая часть достанется и Вам — это что за "трэш, угар и содомия"? Нет, конечно, я видал код и похуже, здесь хотя бы нет магических констант (ну они есть но их немного), но тем не менее, создается ощущение, что ребята из далекой Индии взяли правила MISRA (или другой стандарт встроенного програмирования) и старательно нарушили как можно большее их количество. То есть теперь ТАК принято писать программы и не стыдно выкладывать их в таком виде не всеобщее обосрение (это не ошибка а игра слов).
Во-первых, спасибо за развернутый ответ и содержательное дополнение к статье.

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

Я же хотела поставить задачу иначе — сравнить производительность двух ядер на задаче, приближенной к реальной жизни, и в качестве результата представить ускорение, которое разработчик действительно может получить, сменив кристалл на базе Cortex-M3 на такой же контроллер на базе Cortex-M4F.

Этот подход мне хотелось бы защитить. Представим себе, что я хочу показать как здорово сменить третий cortex на четвертый и пишу об этом статью. В ходе эксперимента я запускаю программу, содержащую только FFT. Отличную расово верную программу с классическим описанием алгоритма. Я получаю восьми, а то и девятикратный выигрыш, и рисую заголовок статьи "Увеличиваем производительность Cortex-M3 в девять раз!!1". Какую же реакцию я получу? Думаю, мы оба понимаем какую)) Доказательство очевидного выигрыша аппаратной реализации плавающей точки над программной — это гораздо менее информативно чем сравнение, например, скорости вычисления частоты света. На конкретном контроллере, конкретной плате и на реальной программе, не подогнанной под ожидаемый результат.

Пожалуй, можно было бы добавить расчет выигрыша по времени на "голое" вычисление FFT, но только чтобы дополнить теоретическую базу статьи.

И я тоже не могу удержаться от маленькой ремарки:

Если я пишу «не верю», то следует читать «мой многолетний опыт заставляет меня сомневаться»

Мы не знакомы, поэтому я также могу предположить что ваше "не верю" несостоятельно, как вы можете предположить что ко мне следует обращаться в мужском роде :-)
Упоминание пола автора в качестве арумента в споре о производительности FFT — это просто удар наповал.
Обычно в хаброподобных интернетах споры сразу становятся бессодержательными после этого упоминания. Пользуюсь по мере необходимости, извините)
Конечно, Вы абсолютно правы, когда говорите о разных показателях, и прирост производительности на вычислениях не эквивалентен увеличению скорости выполнения программы в целом. Поэтому можно и нужно разграничивать эти два показателя. Я только за точность в формулировках, Вы написали
По графикам видно, что энергопотребление кристалла действительно почти полностью определяется уровнем потребления на этапах вычислений и вывода их результатов.… Вычисления на ядре Cortex-M3 проводятся в 2.2 раза медленнее, в той же пропорции изменяется и среднее энергопотребление устройства.
и во второй фразе здесь явно указали на вычисления, хотя в первой говорили о времени в целом. Я привык читать внимательно, и именно поэтому позволил себе некоторые сомнения с последующими уточнения. В свое время (как же давно это было) я реализовывал пакет работы с числами с плавающей точкой на ЦП общего назначения, и с тех пор помню, как это непросто, вот и предположил рост на порядок.

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

Удивлен, что мое предположение (очевидное, основанное на многолетнем опыте, но совершенно неверное, как выяснилось), что мы с Вами имеем одинаковый хромосомный набор, оказалось неверным. Но почему спор должен стать бессодержательным после упоминания пола, я не очень понял. Да, инженер-девушка — это редкость вообще и в электронике в частности, но не вижу оснований для аргументов, не относящихся к делу. Мы же с Вами говорим на одном языке, значит "Мы одной крови, ты и я".

Еще раз извините, если сказал что-то не то, и в мыслях не было кого-то обижать, статья дельная, совсем не бесполезная (а такие, бессмысленные, частенько встречаются), просто чуть подправить бы.
Да, фраза "… Вычисления на ядре Cortex-M3 проводятся в 2.2 раза медленнее .." действительно заслуживает критику. Теперь стало понятно за что у вас взгляд зацепился (ура!).
Я её, пожалуй, не буду убирать, пусть для истории останется.

Какие обиды, что вы! Это же здорово когда настолько внимательно и вдумчиво просматривают твой текст. Тут только спасибо можно сказать)

А вопрос пола привносит самые неожиданные эффекты в разговорах об электронике, поверьте :D
В этот раз я просто хотела подчеркнуть что мы не знакомы, вроде с этим разобрались.
Я просто по другому читать не умею, вот художественную литературу — ту по диагонали, а по технике стараюсь внимательно читать, как известно, "дьявол кроется в деталях", вот к ним и цепляюсь (ну не к орфографии же… цепляться).
По поводу поддержки компиляторами FPU в Cortex M4.
Буквально сейчас на столе лежит платка с STM32F4, использую алгоритм с плавающей точкой. Пришлось немного повозиться в плане того, что что по умолчанию в компиляторах вся арифметика пытается быть с двойной точностью, т.е. double. В частности в компиляторе Keil, все константы — по умолчанию double. И если константа не заканчивается на f (например, 3.1415f), то компилятор эмулирует арифметические действия c double используя FPU, в итоге код исполняется как минимум в 2-3 медленнее.
Поэтому для себя выработал правила:

  • в явном виде типизировать константы, чтобы они были одинарной точности
  • просматривать ассемблерный листинг на предмет вызова непонятных процедур (типа __aeabi_dmul, __aeabi_dadd, etc) в местах где происходят арифметические вычисления
Sign up to leave a comment.