ATS: первые впечатления
Nov. 24th, 2011 06:58 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Занялся я тут изучением ATS и в качестве учебного примера взял задачку nponeccop'a про фильтрацию IP адресов. Дабы не изобретать колеса, взял простое и красивое решение antilamer'a и попытался его почти дословно перевести.
Получилось 108 строк на ATS. Собранное версией ATS 0.2.5 под Cygwin'ом оно работает у меня в полтора раза быстрее, чем антиламерское решение, собранное GHC 6.12.1 (с ключом -О2). На тысяче интервалов и миллионе адресов работает 0.8 секунды (версия на хаскеле - 1.2 с), на 10 миллионах адресов - 8 секунд (а решение на хаскеле 12 с). Ради корректности сравнения оба варианта выдают один и тот же результат (вообще говоря, ошибочный - IP адрес, совпадающий с концом интервала, выкидывается, а интервал из одного адреса и вовсе игнорируется).
Выходит эдакая адская смесь ML, сишечки и теоремодоказательства. Писать на ней тяжело, в первую очередь из-за крайне скудной документации, во вторую очередь из-за довольно странной стандартной библиотеки (представляющую из себя обвешанную зависимыми типами libc и кое-что из базовых библиотек SML), в третью очередь из-за сообщений компилятора, которые выглядят так:
(это я из успешно компилирующейся программы убрал один символ, изменив одно из статических утверждений)
На первый вариант у меня ушло два дня, но он работал на порядок медленнее хаскелевского. Дело было в том, что удобная для использования функция input_line основана на fgetc и сильно тормозит. А чтобы заменить ее на более быструю fgets ушло еще несколько часов, т.к. там типы сильно сложнее, и то не обошлось без читерства (приведение указателя).
Впечатлений масса, чуть позже распишу подробнее и объясню, что все эти закорючки в исходнике означают. Пока лишь замечу, что мой план начать писать на ATS в стиле ML, а потом постепенно вводить зависимые типы провалился: без зависимых типов и доказательств работать со строками, массивами или вводом-выводом нельзя.
Получилось 108 строк на ATS. Собранное версией ATS 0.2.5 под Cygwin'ом оно работает у меня в полтора раза быстрее, чем антиламерское решение, собранное GHC 6.12.1 (с ключом -О2). На тысяче интервалов и миллионе адресов работает 0.8 секунды (версия на хаскеле - 1.2 с), на 10 миллионах адресов - 8 секунд (а решение на хаскеле 12 с). Ради корректности сравнения оба варианта выдают один и тот же результат (вообще говоря, ошибочный - IP адрес, совпадающий с концом интервала, выкидывается, а интервал из одного адреса и вовсе игнорируется).
Выходит эдакая адская смесь ML, сишечки и теоремодоказательства. Писать на ней тяжело, в первую очередь из-за крайне скудной документации, во вторую очередь из-за довольно странной стандартной библиотеки (представляющую из себя обвешанную зависимыми типами libc и кое-что из базовых библиотек SML), в третью очередь из-за сообщений компилятора, которые выглядят так:
/home/user/ats/bin/atsopt --output ips_dats.c --dynamic ips.dats /home/user/ips.dats: 3287(line=89, offs=9) -- 3293(line=89, offs=15): error(3): mismatch of static terms (tyleq): The needed term is: S2Eapp(S2Ecst(at_viewt0ype_addr_view); S2Eapp(S2Ecst(bytes); S2EVar(1284)), S2EVar(1285)) The actual term is: S2Eapp(S2Ecst(at_viewt0ype_addr_view); S2Eapp(S2Ecst(b0ytes) ; S2EVar(1267)), S2Evar(l$3484$3485(6817))) /home/user/ips.dats: 3287(line=89, offs=9) -- 3293(line=89, offs=15): error(3): mismatch of static terms (tyleq): The needed term is: S2Etyarr(S2Ecst(byte); S2EVar(1284)) The actual term is: S2Etyarr(S2Etop(0; S2Ecst(byte_t0ype)); S2EVar(1267)) /home/user/ips.dats: 3287(line=89, offs=9) -- 3293(line=89, offs=15): error(3): mismatch of static terms (tyleq): The needed term is: S2Ecst(byte_t0ype) The actual term is: S2Etop(0; S2Ecst(byte_t0ype)) exit(ATS): uncaught exception: _2fhome_2ffac2_2fhwxi_2fresearch_2fATS_2fIMPLEMEN T_2fGeizella_2fAnairiats_2fsvn_2fats_2dlang_2fsrc_2fats_error_2esats__FatalError Exception(1233) exit(ATS): [ccomp_file_to_file(ips.dats, ips_dats.c)] failed.
(это я из успешно компилирующейся программы убрал один символ, изменив одно из статических утверждений)
На первый вариант у меня ушло два дня, но он работал на порядок медленнее хаскелевского. Дело было в том, что удобная для использования функция input_line основана на fgetc и сильно тормозит. А чтобы заменить ее на более быструю fgets ушло еще несколько часов, т.к. там типы сильно сложнее, и то не обошлось без читерства (приведение указателя).
Впечатлений масса, чуть позже распишу подробнее и объясню, что все эти закорючки в исходнике означают. Пока лишь замечу, что мой план начать писать на ATS в стиле ML, а потом постепенно вводить зависимые типы провалился: без зависимых типов и доказательств работать со строками, массивами или вводом-выводом нельзя.
no subject
Date: 2011-11-24 12:19 pm (UTC)no subject
Date: 2011-11-24 12:20 pm (UTC)no subject
Date: 2011-11-24 03:55 pm (UTC)Хаскельный синтаксис, компиляция в Си с "rudimentary FFI" и Boehm GC. На "сишечку с завтипами" как-то не похоже.
no subject
Date: 2011-11-24 04:35 pm (UTC)no subject
Date: 2011-11-24 01:11 pm (UTC)no subject
Date: 2011-11-24 12:35 pm (UTC)Опять же, расово верного Пресбургера далеко не на все разумные применения хватает.
no subject
Date: 2011-11-24 02:44 pm (UTC)В ATS используется Fourier–Motzkin elimination. Не знаю, как он соотносится с Пресбургером, но сложность вроде та же.
no subject
Date: 2011-11-24 05:51 pm (UTC)Проблемы появляются, когда:
- система линейных ненавенств, к которой сводится теорема в Пресбургере, слишком консервативна. Например, где-то мы что-то делаем или не делаем по условию;
- появляется "домножение на переменную" в каком-нибудь виде (например, вложенный цикл с переменной границей).
no subject
Date: 2011-11-24 06:22 pm (UTC)no subject
Date: 2011-11-25 07:32 am (UTC)Например, если попросить ATS пофильтровать список, про результат можно сказать только то, что он имеет длину не больше исходного списка (консервативная оценка сверху). Аналогично для "взять первые k элементов списка".
Собственно, проблема в том, что на практике такие консервативные "теоремы о длине списка" (или, например, в привычном мне практическом случае, "теоремы о размере промежуточных буферов") "взрываются", то есть, при перемножении нескольких консервативных оценок выдают результат, далёкий от желаемого. А чтобы объяснить системе, что на самом деле она в нескольких местах взяла слишком консервативную оценку, надо сильно постараться.
no subject
Date: 2011-11-24 01:41 pm (UTC)С нетерпением.
no subject
Date: 2011-11-24 09:13 pm (UTC)в моём решении символов в 3 раза меньше: http://inv2004.livejournal.com/144767.html
И работает вроде за сходные цифры, если не быстрее (подождём оффициальных результатов).
no subject
Date: 2011-11-24 09:17 pm (UTC)no subject
Date: 2011-11-25 03:30 am (UTC)Вообще, все правильно, ATS абсолютно не претендует на лаконичность, наоборот, нужно постараться, чтобы на другом языке написать то же самое длиннее. А все потому, что немалую часть программы составляет доказательство корректности. Там нельзя обратиться к i-му элементу массива или строки, не представив компилятору доказательство, что в массиве/строке есть такой элемент. В этих 108 строках гарантируется, что не будет проездов по памяти, не будет некорректного обращения с файлами и не будет зацикливания в рекурсивных функциях парсинга и двоичного поиска. Кроме того, основной цикл с чтением адресов и фильтрацией работает без выделения памяти и нагрузки на GC.
Ну и нашли с чем сравнивать, К и J - короли троллинга по лаконичности. Только они для марсиан, люди такое читать не могут.
no subject
Date: 2011-11-25 09:53 am (UTC)Спасибо за наводку по ATL,даже интересно стало. но я выделил из исходного сообщения, что скорость большая.
И про K я уверен, что это не для марсиан, просто почему-то все очень мнительны в плане синтаксиса, например / - это foldl1 , но почему-то foldl1 (+) [1,2,3] всем нравится, а +/1 2 3 - ужасно для инопланетян. Не понимаю.
уровень вхождения в K очень низкий, раз даже я освоил кое-как. весь словарь: 19 слов (*2 так как монада и диада) + 6 adverbs, из них используются в основном только два ' (map) и / - foldl.
no subject
Date: 2011-11-25 11:08 am (UTC)http://antilamer.livejournal.com/384832.html?thread=3723584#t3723584
90 млн адресов в секунду.
Я попробую у себя скорость чисто поиска померять, только надо будет разобраться, как в ATS это делается.
Про К: "+/1 2 3" еще вяглядит терпимо, но m:0N,{1+|/x#iph}'1+!#ipl это уже совcем %($*#)/1&*$#/1^%+N*0#;@$;^*.
no subject
Date: 2011-11-25 11:28 am (UTC)только 1+ тут на списках работает, а тут пришлось лишний map вставить.
(:) 0 $ map (\x -> map (1+) $ foldl max $ take x iph) $ map (1+) [0..(length ipl)]
# (manad) = length
!X - [0..(X-1)]
1+ - это как 1+ так и map (1+)
{}'l - это map (\->...) l
x#l - take
/ - foldl1
| - max
|/l - foldl1 max l
мне кажется очень просто, как минимум намного проще чем haskell. Я действительно не понимаю что тут такого сложного, кроме стереотипов, что "как-то странно выглядит".
no subject
Date: 2011-11-25 02:31 pm (UTC)no subject
Date: 2011-11-26 01:42 pm (UTC)no subject
Date: 2011-11-25 09:54 am (UTC)no subject
Date: 2011-12-14 11:25 am (UTC)Поэтому сделал такой вот цикл с генерацией случайного числа и его поиском:
Потом просто позапускал 10 млн итераций и 20 млн итераций и вычел время. Использовался набор из 1000 диапазонов, из случайных адресов чуть больше половины попадают в какой-нибудь из них.
Скорость на Q8200 @ 2.33 GHz: 0.187 cек на миллион адресов.
no subject
Date: 2011-12-14 01:02 pm (UTC)тут кстати mrand48 возможно будет очень медленный?
no subject
Date: 2011-12-14 02:44 pm (UTC)Занятно, сейчас собрал и запустил на ноуте с вистой, там mrand48 все время возвращал нули, если сперва не сделать srand. На рабочем компе с семеркой такого не было, случайные числа генерились и без srand.
no subject
Date: 2011-12-14 10:04 am (UTC)no subject
Date: 2011-12-14 10:28 am (UTC)Это с парсингом (строка с адресом - число) али без?
Сорри, я тут отвлекся, так у себя поиск и не померял еще.
no subject
Date: 2011-12-14 10:44 am (UTC)Это без парсинга. просто число, мне кажется, что мало где ip как строка передаётся в реальных системах.