Библиотека CMSIS DSP. Так ли быстр целочисленный квадратный корень?

Небольшое сравнение функции вычисления квадратного корня из библиотеки CMSIS DSP и моей реализации.

Cover Image

Как-то долго я не обращал внимания на эту библиотеку, но вот насталов время.

Там есть куча всяких полезностей, в том числе и быстрых математических функций. И даже вычисление целочисленного квадратного корня. Круто, я смогу отказаться от самописной реализации в пользу той, которую предлагает компания ARM.

Для начала проверим, так ли быстр армовский квадратный корень.

Функция из бибилиотеки DSP имеет два варианта, это 16 бит и 32 бита, флоат версию рассматривать не будем. Моя реализации только версию для 32 бита (на момент начала эксперимента)

С моей версией можно ознакомиться здесь, или же пройти по ссылке на мой пак для Keil'а на gitlab (В разделе "Полезные ссылки")

О CMSIS DSP можно почитать в папке с установленным Keil, у меня это C:/Keil_v5/ARM/PACK/ARM/CMSIS/5.4.0/CMSIS/Documentation/DSP/html/index.html

Приступим к тестам.

Код для тестирования максимально прост, в качестве подопытного выступает Миландр 1986ВЕ92У на частоте 8 МГц.

В текстовом виде код не буду прикладывать, во время теста я не думал о написании этой заметки, а общался с товарищем в вотсапе, вот и слал туда эти картинки.

Описание изображения

Что мы видим? Три вида переменных x8, x16, x32 - это те числа корни которых нужно найти, я заранее посчитал их в блокноте и написал в комментариях.

Далее объявляем пеменные в которых будут результаты, с суфиксом _1 мои, с _2 - ARM. Они объявлены сразу, что бы и мои, и ARM функции были в одинаковых условиях.

Следующие 6 строк это вычисления. А комментарии это время выполнения каждой строчки.

Я думаю сразу заметны различия, что с одной стороны радует, а с другой огорчает.

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

Описание изображения

А теперь самое инетерсное - как ещё ускорить мою функцию?

Самым слабым местом в ней является многократное повторение одного и того же кода:

ax = (d + value / d) >> 1;
d = (ax + value / ax) >> 1;
ax = (d + value / d) >> 1;
value = (ax + value / ax) >> 1;

Столько строк актуально для 32 разрядов, а у нас ещё 16 и 8 есть. Нужно лишь удалить несколько строк и готово. И теперь результаты будут следующими:

  • 16 бит - 0.00000475 сек, что на 0.00000100 сек быстрее моей 32 битной версии и в 3,7 раза быстрее CMSIS DSP
  • 8 бит - 0.00000350 сек, что в 1,6 раза (на 0.00000175 сек) быстрее моей 32 битной версии и в 5 раз быстрее CMSIS DSP, 5 гребаных раз, Карл =)

Неплохое достижение. Но мои функции могут работать только на ядрах Cortex M3 и старше, тогда как библиотека CMSIS DSP может быть использована и на M0. Наверняка вы знаете почему так - нет?

На этом всё. Хорошего кодинга.