Pull to refresh
27
0
Виктор @byman

Пользователь

Send message
«какие ещё пути развития могут быть у Embedded программистов»
Вот сидит Embed программист на горе со своим знанием IDE, микроконтроллера, С++,
а что запрограммировать ( «сделать что-то стоящее»(с) ) не знает :) Этому вопросу тоже стоит уделять внимание — куда приложить ваши знания и умения. Не моргать же всю жизнь светодиодами :)
Трюки действительно интересные, но очень затратные в плане тактов процессора. Без FMA очень проблематично использовать two_prod (); На своем процессоре я влез только в 17 тактов. А если все это еще делать через вызов-возврат функции, экономя код, то уже задумаешься. С two_sum () тоже 8 тактов (с учетом пузырей). Так что если в итоге все потом посчитать, то уже и другие алгоритмы могут быть привлекательными.
После серии хороших уроков, а также после портирования на свой процессор пакета для вычисления с quad-double точностью, уже совсем иначе читаешь следующий урок :)
Может кто встречал в сети какие-то отчеты по быстродействию различных процессоров на тестах с quad-double точностью? Было бы интересно посмотреть.
Во многих процессорах операция с nan может приводить к программному исключению. Правда эта функция может быть и выключена. Так что программное исключение тоже может быть результатом вычисления приведенного примера:)
О правильном порядке вычислений :)
Переписал s_sin на ассемблер, чтобы оценить скорость вычисления. При переборе синуса на 100 млн чисел с некоторым шагом, на 2-х числах ассемблерная реализация не совпала с Си-шной (отличался младший бит). Оказалось, что в ассемблере выражение x * xx * (sn3 + xx * sn5) я сделал так: xx * sn5, +sn3, * xx, *x :)
Спасибо. C s_sin я уже активно работаю :) У меня имеется своя реализация sin-cos (некоторые подробности реализации я изложил в части 2). Интерес к s_sin у меня как к генератору эталонного результата. Также в s_sin мне понравились некоторые приемы работы с double. Моя реализация очень мала по обьему кода и по размеру таблицы (80 байт) и имеет очень хорошую скорость. Длина полинома у меня на два члена длиннее чем в s-sin. Цель — улучшить точность, незначительно потеряв в скорости. Вполне возможно, что я реализую на ассемблере и s_sin, как альтернативный вариант в библиотеке.
Спасибо. Именно об этом и был мой вопрос. Попробую посмотреть, может чего и пойму :)
А то жалко иметь хороший аппаратный double, а расчеты производить на счетах, потому что точнее выходит :)
1. я как раз про свой конкретный случай :) в моем процессоре можно 2 double умножения за такт, но ни одного int64*int64. Эксперимент с sin_e7 примером я провел. Реализовал команду умножения int64*int64 через последовательность умножений int32*int32 и сложений.
2. насколько я помню, FMA избегает ненужного округления перед сложением. Результат будет немного точнее. Но у меня нет и FMA :) Только умножить и сложить.
3. Да, я использовал такой подход в синусе. Тот еще геморрой :)
«Всё-таки long double достаточно экзотический вид данных и его поддержка в современных процессорах не является приоритетной».
А если в процессоре нет целочисленного умножения 64*64? :) Можно конечно через 32*32,
но это в 10 раз медленнее чем double*double.
Правильно ли я понимаю, что если в сложении-вычитании double можно производить вычисления большей точности за счет double.double, то с умножением такой фокус не проходит? Умножили и хвост безнадежно потерян. Кстати, в процессоре можно легко сделать вычисления double+double c сохранением обоих частей результата. Аналогично можно было бы сделать и с умножением. т.е. по аналогии с целыми числами int*int = long long.
Был бы какой-то толк от подобных инструкций?
Просмотрел код. Оказалось, что константы полинома я взял свои, а в s_sin они почему-то другие. Подставил правильные и ничего не поменялось :) сложно это — точные вычисления :)
Спасибо. Ваш ответ я понимаю как то, что результат s_sin для
sin(0х40F7A79D c28f5b10) есть 0хBF4FCE42 60D79B24. К сожалению, не знаю как в вольфраме посмотреть результат в hex формате :)
Буду смотреть в чем у меня причина иного поведения.
Я провел сравнение результатов своей функции и функции s_sin на интервале от 0 до
пи\2 (чтобы не задействовать случай с редукцией) с шагом равным делению интервала на количество итераций.
Для миллиона итераций отличие не больше 2-х младших бит мантиссы. Для 100 млн итераций плохими оказались 3 бита. При этом одинаково ведут себя как функция со строгим порядком вычисления полинома, так и в случае деления полинома на две части.
Я при вычислении использую таблицу из 5-ти значений, т.е. интервал [0-пи\2] у меня разбит на 5 секторов. Отличия от s_sin появляются когда входное значение попадает в тот случай где s_sin использует таблицу и более точное вычисление.
Сам синус я вычисляю через sin(a+b) = sin(a)*cos(b) + cos(a)*sin(b)
a есть значение сектора, т.е. sin(a) cos(a) константы из таблицы
Запустил s_sin.c на своем процессоре.
Есть немного удивительные для меня результаты.
У меня есть таблица эталонов из 1024 элементов, которые я когда-то подготовил в MVS
для интервала от 0 до 4.69398121 с некоторым шагом.
Функция s_sin.c дала 100% совпадение с эталоном.
При этом моя функция на половине значений дает ошибку в младшем бите.
И есть несколько значений где разница мантисс равна 2, а не 1.
И это при том, что длина полинома у меня чуть больше чем у s_sin.c :)
Затем решил я проверить одно число, с которым у меня были проблемы. Входной аргумент
val = 0х40F7A79D c28f5b10 довольно большое число (96889.859999995911) и требуется
серьезная редукция. Результаты:
в MVS = 0xBF4FCE42 611d2228
моя функция = 0хBF4FCE42 611d1da9
функция s_sin.c = 0хBF4FCE42 611d1da9
Результат вольфрама 0хBF4FCE42 60D79B24
Почему у меня плохой результат я понимаю, но почему такой же и у s_sin.c :)
Может кто перепроверит результат s_sin.c на данном значении.
Спасибо. Я вот за утро поделил свой полином на две части (чет и нечет) и немного ускорил вычисления. Полином у меня не очень длинный (до x**15), да еще с нечетным количеством членов. Но все равно на самом полиноме я выиграл 25% в скорости. Все ваши слова о точности пока подтверждаются и в моих вычислениях. Но пока это было несколько тысяч когда-то заготовленных значений. Буду сейчас внимательно читать, что написал dorex и попробую сравнить результаты на «плохих» аргументах. :)
Изменение порядка вычислений на точности никак не скажется? или отличие несущественное?
Не знаю как в крутых процессорах, но вот на моем VLIW DSP in-oder, запросто можно считать одновременно синус и косинус. Также можно еще что-нибудь посчитать (за те же такты), т.к. эти полиномы очень неудобны для конвейера — текущий результат нужен для следующей операции. А из-за этого пузыри на конвейере. В эти пузыри можно впихнуть что-то полезное. Своеобразный ручной гипертрейдинг :) Главное чтобы эти параллельные вычисления не нуждались в переходах, ну и вычислительная сложность была приблизительно одинаковой.
При написании библиотеки для своего VLIW DSP процессора первая проблема с синусом была в том, как точнее привести аргумент к нужному диапазону. Иначе дальше уже бессмысленно что-то точно считать. А еще при реализации функции одновременного вычисления синуса и косинуса (получались те же такты что и у одиночной функции) у меня почему-то синус получался точнее чем косинус. Надеюсь, что благодаря последним статьям о точных вычислениях с double мне удастся улучшить свои функции :)
Вы говорите про общий случай. Но для своего теста мне был удобнее именно такой подход. Спасибо за ссылку о сортировке, а то я еще не дочитал, но уже пишу :)
А как будет с лицензией если питерского Медведя кто-то купит или он сьедет на работу в заграничную компанию? :)
Этот алгоритм проще было бы показать на числах float, а точный результат посчитать с помощью double. Еще суммирование таких чисел зависит от порядка их следования. Так что если не отсортировать, то точность не будет идеальной. После первой статьи я написал пару тестов на своем процессоре и случайно обнаружил, что «старое» суммирование, но с SIMD подходом, дало лучший результат чем алгоритм Кахана. Просто порядок следования чисел был для SIMD удачнее :)

Information

Rating
5,445-th
Location
Беларусь
Registered
Activity