- •Общее
- •О языке
- •Встроенные функции
- •Операции композиции
- •Типы данных
- •Описание программы
- •Процесс выполнения функциональной программы
- •Вызов программы
- •Полный пример программы
- •Интерпретатор и компилятор языка FPTL
- •Кластерный интерпретатор
- •Как достигается автоматический поиск переносимых ФП?
- •Как мы находим мемоизуемые ФП?
- •Как мы поддерживаем любое кол-во машин в кластере и процессоров на машине?
- •Массивы в языке FPTL
- •Компилятор программ языка FPTL
- •Характеристики компилятора
- •Тесты компилятора
- •Вычисление интеграла с заданной точностью
- •Тест рекурсии из комплекта тестов с сайта http://shootout.alioth.debian.org/gp4/benchmark.php?test=recursive&lang=all
- •Вычисление значения N-ого числа Фибоначчи на типе данных Nat
- •Разделение строки на лексемы
- •Приложение – тексты тестовых программ
- •Вычиcление интеграла с заданной точностью – Java
- •Вычиcление интеграла с заданной точностью – FPTL
- •Тест рекурсии - Java
- •Тест рекурсии – FPTL
- •Вычисление значения N-ого числа Фибоначчи на типе данных Nat – Java
- •Вычисление значения N-ого числа Фибоначчи на типе данных Nat – FPTL
- •Разделение строки на лексемы – Java
- •Разделение строки на лексемы – FPTL
Для функций, чей результат используется в нескольких точках программы, генереируется отдельный вызов для вычисления данных функций. После этого используется только их результат. Прямая подстановка делается только для констант и уже объявленных переменных. Примером таких функций может быть функция F в коде F.(G*H), где результат F будет использоваться на входе у G и H.
Кнесделанным на данный момент оптимизациям можно отнести только поиск и вынесение «за скобку» общих подвыражений в функции. Они часто могут появляться как результат подстановки простых функций в сложную. Однако, эксперименты над получаемым исходным кодом показывают, что заметный выигрыш от этой оптимизации мы можем получить только в редких случаях. Это и является причиной того, что данная оптимизация пока не была сделана.
Тесты компилятора
Приведу несколько примеров времени выполнения программ в интерпретируемом и компилируемом режимах. Все программы из этих примеров есть в конце данной статьи (файлы java являются сгенерированными промежуточными файлами компилятора. Из них я удалил только отладочные комментарии.). При желании вы можете реализовать их на своем любимом компиляторе и сравнить результаты. Все тесты выполнялись на процессоре Intel Pentium Mobile ULV 1.1 GHz, с оперативной памятью 1280 Mb (ноутбук Dell Latitude X1).
Вычисление интеграла с заданной точностью
Худший случай для компилятора. Это пример времени выполнения программы, не переводимой в итеративную форму. В процессе генерируются переменные var9 и var18, которые пока не оптимизируются текущей версией транслятора.
Интеграл вычисляется по формуле
INT = | Trp(a, (a+b)/2) + Trp((a+b)/2,b) – Trp(a,b) | < E -> Trp(a,b),
INT(a, (a+b)/2, E/2) + INT((a+b)/2, b, E/2)
где Trp – функция вычисления площади фигуры по методу трапеций на интервале от a до b.
Интеграл берется от функции x2 на промежутке от 0 до 10 с точностью 1e-8.
Все вычисления ведутся на одном и том же компьютере.
Компилированный код: 0.12 секунд
Интерпретатор: 3.1 секунд
Тест рекурсии из комплекта тестов с сайта http://shootout.alioth.debian.org/gp4/benchmark.php?test=recursive&lang=all
Компилированный код: 3.844 сек
Интерпретируемый код в данном тесте мемоизует функции ACK, FIBD, TAK. Без поддержки мемоизации время выполнения слишком велико. А вот с мемоизацией интерпретатор сразу обгоняет компилированный код: 1.828 сек!!!