Войти
ПрограммированиеФорумОбщее

Exp + ряд Маклорена

Advanced: Тема повышенной сложности или важная.

Страницы: 1 2 Следующая »
#0
(Правка: 19:02) 19:00, 30 мая 2019

Всем привет!

Хотел сделать вычисление экспоненты и взял за основу ряд маклорена.
В общем считает правильно, но в диапазоне X=[0.0..PI]
После PI начинается расхождение и чем выше X, тем сильнее расхождение.
Подскажите, если кто сталкивался, в чем проблема?

Код Delphi XE6 для Win32.

+ Показать

Результат работы для единицы и числа PI:

+ Показать

#1
(Правка: 21:34) 21:28, 30 мая 2019

eDmk
> в чем проблема?

Сейчас точно не помню, но вроде бы при вычислении экспоненты учитывают тот факт, что число представлено мантиссой и порядком, то есть что оно является произведением M * 2^P, и, соответственно вычисляют отдельно экспоненту (по основанию 2) от мантиссы, и отдельно от порядкового множителя 2^P (фактически 2^P просто само по себе становится порядком, т.к. это двоичная система счисления). Дальше эти два числа "перемножают" (а фактически, второе число имеет мантиссу=1, так что просто его порядок складывают с порядком первого числа).

Естественно, вычисляют экспоненту по основанию 2. Для других оснований просто по формуле для экспоненты одного основания через экспоненту другого основания (фактически просто умножение аргумента на константу).

Ну и еще учитывай, что FPU оперирует внутри 80-разрядной плавучкой, а не 64-разрядной.

#2
22:14, 30 мая 2019

eDmk
> После PI начинается расхождение и чем выше X, тем сильнее расхождение.
Потому что ряд Маклорена — он вблизи нуля работает, а чем дальше — тем хуже.
Если интересно, то в любой книжке по матану написано, как оценивать погрешность подобных рядов.
И еще расчет полинома у тебя кривой, см. схема Горнера. Она не оптимальна с точки зрения параллельности, но это уже следующий уровень сложности.

Ну и на практике ряды Тейлора для вычислений функций не используют, в принципе.
Надо использовать, хотя бы, полиномы Чебышева, или сразу оптимизацию по [cht]L_\infty[/cht] норме.

Dmitry_Milk
> Ну и еще учитывай, что FPU оперирует внутри 80-разрядной плавучкой, а не 64-разрядной.
Только устаревшие компиляторы в режиме совместимости.

#3
6:52, 31 мая 2019

eDmk
> Q := (X * X); //^2
> R := R + Q * FExpTab[0]; //2!
>
> Q := (Q * X); //^3
> R := R + Q * FExpTab[1]; //3!
>
> Q := (Q * X); //^4
> R := R + Q * FExpTab[2]; //4!
>
> Q := (Q * X); //^5
> R := R + Q * FExpTab[3]; //5!
>
> Q := (Q * X); //^6
> R := R + Q * FExpTab[4]; //6!
>
> Q := (Q * X); //^7
> R := R + Q * FExpTab[5]; //7!
>
> Q := (Q * X); //^8
> R := R + Q * FExpTab[6]; //8!
>
> Q := (Q * X); //^9
> R := R + Q * FExpTab[7]; //9!
>
> Q := (Q * X); //^10
> R := R + Q * FExpTab[8]; //10!
>
> Q := (Q * X); //^11
> R := R + Q * FExpTab[9]; //11!
>
> Q := (Q * X); //^12
> R := R + Q * FExpTab[10]; //12!
>
> Q := (Q * X); //^13
> R := R + Q * FExpTab[11]; //13!
>
> Q := (Q * X); //^14
> R := R + Q * FExpTab[12]; //14!
>
> Q := (Q * X); //^15
> R := R + Q * FExpTab[13]; //15!
>
> Q := (Q * X); //^16
> R := R + Q * FExpTab[14]; //16!
>
> Q := (Q * X); //^17
> R := R + Q * FExpTab[15]; //17!
>
> Q := (Q * X); //^18
> R := R + Q * FExpTab[16]; //18!
>
> Q := (Q * X); //^19
> R := R + Q * FExpTab[17]; //19!
>
> Q := (Q * X); //^20
> R := R + Q * FExpTab[18]; //20!
>
> Q := (Q * X); //^21
> R := R + Q * FExpTab[19]; //21!
>
> Q := (Q * X); //^22
> R := R + Q * FExpTab[20]; //22!
>
> Q := (Q * X); //^23
> R := R + Q * FExpTab[21]; //23!
>
> Q := (Q * X); //^24
> R := R + Q * FExpTab[22]; //24!
>
> Q := (Q * X); //^25
> R := R + Q * FExpTab[23]; //25!
>
> Q := (Q * X); //^26
> R := R + Q * FExpTab[24]; //26!
>
> Q := (Q * X); //^27
> R := R + Q * FExpTab[25]; //27!
>
> Q := (Q * X); //^28
> R := R + Q * FExpTab[26]; //28!
>
> Q := (Q * X); //^29
> R := R + Q * FExpTab[27]; //29!
>
> Q := (Q * X); //^30
> R := R + Q * FExpTab[28]; //30!}
лол, тяжело, наверное, программировать, когда тебя в циклах забанили

#4
7:19, 31 мая 2019

Suslik
> лол
Вам наверно неизвестно, но развернутые циклы работают быстрее.
Команда loop или jmp имеют латентность, а развернутый цикл не имеет.
А если все это поместить в регистры, то скорость вырастает в разы.

Умножать в цикле можно, вот например:

+ Показать

но так быстрее на 30%:

+ Показать

#5
7:36, 31 мая 2019

eDmk
> но так быстрее на 30%:
я не верю, что у дельфи настолько убогий оптимизатор

#6
9:26, 31 мая 2019

Suslik
> я не верю, что у дельфи настолько убогий оптимизатор
>
>
К сожалению оптимизатор там точно убогий, как и сам компилятор.
Но есть плюсы - он очень шустрый и есть встроенный асм.
Так что оптимизированная версия умножения матриц выглядит иначе:

+ Показать

И она шустрее языковой версии раза в 3. Т.к. оптимизированный ручками асм.

#7
9:33, 31 мая 2019

eDmk
> Но есть плюсы - он очень шустрый и есть встроенный асм
плюсы есть не в дельфи, они есть в C++

eDmk
> И она шустрее языковой версии раза в 3. Т.к. оптимизированный ручками асм.
если компилятор не может сгенерить такой код из цикла, это значит, что компилятор — полное фуфло. серьёзно, тут даже не о вкусе речь. если из-за немощности компилятора нужно свой код превращать в стену никчёмной копипасты, то имеет смысл задуматься о том, чтобы его сменить.

#8
10:31, 31 мая 2019

Suslik
> если из-за немощности компилятора нужно свой код превращать в стену никчёмной
> копипасты
Тут вы неправы. У меня весь код написан мной. Ни одной строчки не заимствовано.
"GLM" у меня свой. Класс камеры - свой. Загрузчик картинок - свой. Класс окна - свой.
Надстройки свои. Компоненты свои. Загрузчик объектов - свой. Работа с памятью - сам делал.
+ свой растровый GAPI. Порядка 70-и своих модулей. VCL полностью выключен. Чистый WinApi.
От системы только ввод/вывод + GAPI OpenGL.

> компилятор — полное фуфло
Не совсем конечно так. Он работает нормально, только с оптимизацией не очень.

> имеет смысл задуматься о том, чтобы его сменить
VisualStudio стоит денег, а Delphi уже куплен. Пока не могу сменить.

#9
10:32, 31 мая 2019

Suslik
> плюсы есть не в дельфи, они есть в C++
C++ нормальный язык. Никогда ничего не имел против.

#10
11:54, 31 мая 2019

Suslik
> они есть в C++
Вот софтрендер запиленный на Delphi + асм:

+ Показать

Работает на 1-м ядре. На мой взгляд достаточно шустро, хотя можно и быстрее.
#11
13:33, 31 мая 2019

eDmk
> Не совсем конечно так. Он работает нормально, только с оптимизацией не очень.
это и значит, что компилятор — херовый.

eDmk
> Тут вы неправы. У меня весь код написан мной. Ни одной строчки не заимствовано.
> "GLM" у меня свой. Класс камеры - свой. Загрузчик картинок - свой. Класс окна -
> свой.
> Надстройки свои. Компоненты свои. Загрузчик объектов - свой. Работа с памятью -
> сам делал.
> + свой растровый GAPI. Порядка 70-и своих модулей. VCL полностью выключен.
> Чистый WinApi.
> От системы только ввод/вывод + GAPI OpenGL.
какая мне разница, кем там твой код написан. если на перемножение матриц 4x4 уходит экран текста, то никто с таким кодом работать не будет, потому что в таком коде невозможно искать баги, невозможно его отлаживать и расширять. твоей первоочередной задачей должно быть написание высокоуровневых алгоритмов и максимально понятного и прозрачного кода, который легко читать, понимать и расширять, а разворачивать циклы за тебя должен оптимизирующий компилятор, потому что у него работа такая.

eDmk
> VisualStudio стоит денег, а Delphi уже куплен. Пока не могу сменить.
вообще-то community edition бесплатный для подобных проектов, да и вообще любой gcc/clang уж подобный цикл точно за тебя развернёт и векторизует хоть на sse/ss2, хоть на avx.

#12
(Правка: 18:50) 18:24, 31 мая 2019

eDmk
> Код Delphi XE6 для Win32.
попробуй Extended на double заменить.
какой будет результат? (скорость, точность)

Suslik
> если компилятор не может сгенерить такой код из цикла, это значит, что компилятор — полное фуфло.
> серьёзно, тут даже не о вкусе речь. если из-за немощности компилятора нужно свой код превращать в стену никчёмной копипасты,
> то имеет смысл задуматься о том, чтобы его сменить
Отдельные люди могут сказать, что какая нафиг разница, как выглядит тело функции, если она проверена и работает.
(если смотреть в функции криптографии, там такой стиль сплошь и рядом)
Тело может может быть хоть в 10,000 строк, хоть азм, под конкретную платформу.
В основном коде, вызов это всё-равно одна строчка.

Но, в Делфи, действительно, особо оптимизацией не задумываются.
Зато в FPC, тусит могучая кучка народу, которая как раз увлекается такой вот оптимизацией, с целью догнать всякие Си и llvm.
(да и под llvm и fpc и delphi, тоже точатся)

Если сегодня компилятор, выдаёт неспешный код, то уже (после(после(после))) завта, производительность окажется 1 в 1 с clang-ом.

При этом сами исходники не поменяются; из побочных бонусов: скорость компиляции и отсутствие крестопроблем.

...на крайний случай, можно сделать Си-оптимизиацю.
Написать Взять готовую функцию на Си,  собрать объектный файл, и прилинковать.  (никакие реализации JPEG на паскале, с си-шным оригиналом тягаться в производительности не могли)
Как было уже сказано: "какая нафиг разница, как выглядит тело функции, если она проверена и работает"

#13
18:54, 31 мая 2019

skalogryz
> попробуй Extended на double заменить.
> какой будет результат? (скорость, точность)
Только не это! Я как раз перелез под FPU. Точность совпала до 18 знака с системной Exp.
В Double прдеставления числа не хватает к сожалению.
Скорость мне сейчас не важна. Мне нужно смасштабировать Exp на числа выше PI.
Иначе сильные расхождения появляются. На порядки.
Этот ряд некорректно считает или я не так что-то делаю.

#14
18:56, 31 мая 2019

eDmk
> Зато в FPC, тусит могучая кучка народу
Да, неплохо они сделали. FPC все лучше и лучше.
Лучше бы туда дебаггер нормальный приделали. Я бы ваще с Delphi слез бы.
Там и кросс платформенность и AVX, AVX2, AVX512 и ваще.

Страницы: 1 2 Следующая »
ПрограммированиеФорумОбщее