Украинское сообщество программистов

Мой любимый неторопливый питон

Александр Бельченко
Опубликовано 2.06.2007 в Статьи

Я люблю язык программирования Питон. Люблю как программист и как пользователь. Я люблю использовать программы, написанные на этом языке. В списке моих излюбленных инструментов находятся 3 великолепные питон-программы:

  • для ведения документации я использую пакет docutils (http://docutils.sf.net)
  • для сборки сишных проектов я использую SCons (http://www.scons.org)
  • для ведения истории моих проектов я использую децентрализованную систему контроля версий Bazaar (http://www.bazaar-vcs.org)

Эти 3 программы объединяет 2 свойства:

1) они написаны на питоне
2) они медленно работают (как ни горько это сознавать)

Причем 2е неявно вытекает из 1го. Причем медленность эта проявляется в 2х случаях:

1) на медленных старых машинах
2) на больших объемах данных для обработки

И если с 1м фактором бороться как-то можно (но не всегда), то 2й фактор порой действует просто убийственно.

Все мы (или по крайней мере многие из нас) знаем, что Питон медленный, и не рекомендуется для обработки огромных массивов данных. Что на нём очень быстро и удобно писать программы. И потому очень хорошо использовать для макетирования и прототипирования.

Но где-то здесь, мне кажется, таится фундаментальная ошибка. Подвох. Обман.

При переходе от макета к рабочей версии получается нужно писать все заново на сях или плюсах? При этом или заново изобретать велосипед и вводить свои реализации высокоуровневых питон-объектов, таких как списки, словари или связанные методы, либо стараться не использовать подобные вкусности питона в макете, чтобы меньше потом переделывать? К тому же огромная мощь Питона отчасти обеспечивается его огромной стандартной библиотекой, включая огромный арсенал дополнительных средств. Как быть с ними? Да и его кросс-платформенность многого стоит. На самом деле.

Возможно введение необязательной статической типизации в Питоне 3000 как-то поможет в проблеме создания высокоэффективных jit-компиляторов для Питона, либо трансляторов в C++. Но сегодня… М-да.
Остается только надеяться, что однажды можно будет в C(D?) программе написать:

for item in some_list:
do_something(item)

А пока можно поизвращаться с игрушками типа p++ и ShedLight.

Теги: , , , ,

1 звезда2 звезды3 звезды4 звезды5 звезд (Еще не оценили)
Загрузка ... Загрузка ...

Понравилась статья? Подпишись на обновления по RSS/E-mail

Подписаться, не оставляя комментарий

Все комментарии (25) к “Мой любимый неторопливый питон” RSS

  1. Vadim

    По поводу
    for item in some_list:

    в последней версии boost вроде появилась конструкция FOR_EACH.

  2. koder

    в последней версии boost вроде появилась конструкция FOR_EACH

    Она на С++ пишется на раз и без всякого boost

    template for_each(Cont & cont,Callb & callb){
    Cont::iterator it = cont.begin();
    for(;it != cont.end();++it)
    callb(*it);
    }

    Теперь по делу собственно:
    1)В основном низкая скорость обусловлена кривым алгоритмом а не языком, я один
    раз в весьма серьезной научной программе пузырьковую сортировку нашел, а ее
    автор долго удивлялся че это она так тормозит на больших объемах данных.
    2)В нете есть вагон документации по оптимизации питоновских программ. Чаще всего
    не нужно переписывать всю прогу а достаточно прооптимизировать
    самые “жрущие” проц. ф-ции/блоки. Причем сначало psyco затем PyRex и только
    затем pure-C/C++. После применения этого метода лично меня результаты по скорости
    вполне устраивали.
    3)Используйте правильные библиотеки(типа scipy) – это решает массу проблем
    (если они есть, конечно, но чаще всего они таки есть).

  3. bialix

    Теперь по делу собственно:
    1)В основном низкая скорость обусловлена кривым алгоритмом а не языком

    А вот Вы лично и сходите в список рассылки тех же docutils и scons и поучите их уму-разуму. А то ребята который год не могут правильный алгоритм выбрать.

    Если честно — все написанное Вами настолько тривиально и избито… Однако проблема все равно имеет место быть. И будет. И пока что решается только одним путем — использования самого быстрого компьютера из имеющихся.

  4. Скакунов Александр

    Я далекий от питона человек, но, учитывая написанное выше, меня удивляет, почему Гугл с их гуглоподобными объемами данных пишут на этом языке (вернее, в том числе на этом).

  5. xxx

    предлагаю пререписать на ассемблере

  6. Vityok

    почему Гугл с их гуглоподобными объемами данных пишут на этом языке (вернее, в том числе на этом)

    Як варіант відповіді — Python використовується на «вищому» рівні для поєднання компонент, написаних на C/C++.

    Хоча, дійсно, існують і інші мови програмування високого рівня з швидкими інтерпретаторами/компіляторами.

    PS. : колись Yahoo! відкрила свій власний документ про переваги переходу з YahooScript на PHP.

  7. motus

    в последней версии boost вроде появилась конструкция FOR_EACH

    Она на С++ пишется на раз и без всякого boost

    :-) учите устав STL, двоечники – std::for_each() уже сто лет как стандарт. заодно рекомендую обратить внимание, что в STL конец контейнера передается отдельным параметром, и что функциональный объект передается по значению. (вопрос “зачем” оставляем читателям в качестве упражнения) :-)

    меня удивляет, почему Гугл с их гуглоподобными объемами данных пишут на этом языке

    насколько я знаю, в гугле питона не так много, как все считают.. пару лет назад была презентация на эту тему: python at google.. гугл, кстати, активно использует SWIG – странно, что про него никто не вспомнил.

    еще вроде популярный вариант – Boost::Python, но я его не использовал никогда.

    колись Yahoo! відкрила свій власний документ про переваги переходу з YahooScript на PHP.

    yScript. это не внутренний документ, и не один. ты скорее всего про это:

    http://www.radwin.org/michael/blog/2005/10/php_at_yahoo_presentation_.html

    хотя, наверное, более ранняя презентация информативнее: http://public.yahoo.com/bfrance/radwin/talks/yahoo-phpcon2002.htm

    а вот тут они все: http://public.yahoo.com/bfrance/radwin/talks

  8. Сергей

    Медленно работают? А есть причины полагать что можно быстрее? Может просто действительно данных очень много?

  9. bialix

    Медленно работают? А есть причины полагать что можно быстрее? Может просто действительно данных очень много?

    Есть причины полагать, что да. Эта причины — программы-конкуренты.
    Но данных действительно очень много. Порой.

    В общем еще одна вещь, от которой спасает только быстрая машина — это очень медленный старт самого интерпретатора Питона. Вы пробовали когда-нибудь запустить Питон на Целероне 300 МГц? Вот когда узнаешь, что значит слово “терпение”

    :-)

  10. Ferroman

    Низкая скорость питона имеет место быть. Однако программы написанные на Java/.NET тоже медленны (по сравнению с C++). Это – расплата за вкусности и кросплатфоренность. И действительно, бороться с этим можно только переводя части кода на более быстрые языки. И конечно использовать только к подходящим задачам.
    Бо “Нема на то ради” (с)

  11. Anonymous

    Однако программы написанные на Java/.NET тоже медленны (по сравнению с C++).

    Если это не вычислительные задачи (типа перемножения матриц), то в среднем С# отстаёт от С процентов на 20. Языки же вроде питона и руби проигрывают в разы!

  12. koder

    bialix:

    А вот Вы лично и сходите в список рассылки тех же docutils и scons и поучите их уму-разуму. А то ребята который год не могут правильный алгоритм выбрать.

    docutils не использовал, а производительность scons вполне приемлемая. В любом
    случае компилятор съедает основную часть времени(в случае с docutils могу
    сказать что крайне низкая скорость работы LaTeX почему-то никого не волнует).
    Ваша статья затрагивает их только как пример, а дальше идет рассуждение на тему
    какой питон тормоз и что нет от этого спасения так что и советы не относились к
    ним конкретно, а имели общий характер.

    Если честно — все написанное Вами настолько тривиально и избито…

    Безусловно, но написанное в заметке ему явно противоречит.
    А именно это:

    При переходе от макета к рабочей версии получается нужно писать все заново на сях или плюсах?

    , на что и был ответ, что нет, не все нужно переписывать(кроме некоторых исключений), в основном можно обойтись малой кровью(примеров масса – cheetah один из них).

    И пока что решается только одним путем — использования самого быстрого компьютера из имеющихся.

    Программы типа scons безусловно не расчитаны на Celeron 300, там Вас только
    make и спасет. Я предлагаю Вам привести пример быстрых систем, подобных по
    возможностям к scons(желательно не тормозящих на указанной машине).
    Для примера – jam(boost) тормозит если и меньше, то несущественно.
    И AFAIK обладает существенно меньшим количеством возможностей.

    motus:

    :-) учите устав STL, двоечники – std::for_each() уже сто лет как стандарт. заодно рекомендую обратить внимание, что в STL конец контейнера передается отдельным параметром, и что функциональный объект передается по значению. (вопрос “зачем” оставляем читателям в качестве упражнения) :-)

    Приведен __ПРИМЕР__ наиболее близкий к питоновскому map(function,object).
    В stl отдельным параметром передается не только конец контейнера, но и его
    начало(собственно контейнер вообще не передается).
    Теперь предлагаю motus поупражнять знание питона и подумать почему я передал
    функциональный объект по ссылке(намекаю – это было сделано специально).
    И, кстати, этот пример замечательно работает не только к функторами но и с
    функциями.

  13. koder

    В догонку.
    Просмотр списка рассылки scons указал на то что основная часть
    проблем(кстати всего ~10 небольших тредов затрагивают производительность за более чем 3 года при более 10000 писем в рассылке в сумме) связанна
    как раз с неоптимальными алгоритмами, а не с торможением собственно питона.
    Пример : http://scons.tigris.org/servlets/ReadMsg?list=users&msgNo=1834.
    этот то-же поучительный http://scons.tigris.org/servlets/BrowseList?list=users&by=thread&from=259418
    (только не останавливаемся на первом письме, а читаем дальше)
    Так-же можно обратится к проектам Scons на Google
    SOC(http://www.scons.org/wiki/GSoC2007) – там тоже ничего про общую
    оптимизацию, а только улучшение алгоритма отслеживания измененных файлов.

  14. motus

    koder:

    Приведен __ПРИМЕР__ наиболее близкий к питоновскому map(function,object).

    хм. ну тогда можно было и поближе найти, как мне кажется. питоновский map(), насколько я понимаю, возвращает новый список – это ближе к std::copy() или std::transform() + insert_iterator, но никак не к for_each(), тем более в том виде, в каком вы его написали.

    В stl отдельным параметром передается не только конец контейнера, но и его
    начало(собственно контейнер вообще не передается).

    ну это и ежу понятно. впрочем, если придираться к словам, то стандартные алгоритмы вообще не знают ни про контейнеры, ни про их “начало” и “конец”. пример – тот же std::for_each() + std::istream_iterator.

    Теперь предлагаю motus поупражнять знание питона и подумать почему я передал
    функциональный объект по ссылке(намекаю – это было сделано специально).

    я питон знаю плохо, но упражняться люблю. my guess – это просто потому, что в питоне все передается по ссылке. теперь, пожалуйста, скажите правильный ответ.

    впрочем, я другое хотел сказать с самого начала: в каждом языке есть свои паттерны и идиомы, и нечего в С++ лепить свой for_each(), если уже есть STL. он не такой, как map() в питоне, но и С++ другой язык.

    И, кстати, этот пример замечательно работает не только к функторами но и с
    функциями.

    surprise, surprise – передача по значению и стандартные алгоритмы прекрасно работают с обычными С функциями, напр.

    std::transform(str.begin(), str.end(), str.begin(), toupper);

  15. koder

    хм. ну тогда можно было и поближе найти, как мне кажется. питоновский map(), насколько я понимаю, возвращает новый список

    Да, с map я описался, он тут совсем не причем, приведен пример соотв. требуемому
    for i in storage:func(i)

    ну это и ежу понятно. впрочем, если придираться к словам,

    Придиратся к словам начали Вы, это был просто ответ в том-же духе.

    my guess – это просто потому, что в питоне все передается по ссылке

    +1. Так-же потому что иногда объект накапливает определенную информацию при прохождении массива, что используется уже после цикла/map.

    surprise, surprise – передача по значению и стандартные алгоритмы прекрасно работают с обычными С функциями, напр

    Я и не говорил что они не могут, но вот если бы у себя в прототипе я написал
    template<class X,class Y> int for_each(X &,const Y &){….}
    то вместо Y уже нельзя было-бы подставить ф-цию. Это был ответ на

    и что функциональный объект передается по значению. (вопрос “зачем” оставляем читателям в качестве упражнения)

    , насколько я понял именно
    на невозможность использования ф-ций с const X & и намекалось.

    впрочем, я другое хотел сказать с самого начала: в каждом языке есть свои паттерны и идиомы, и нечего в С++ лепить свой for_each(), если уже есть STL. он не такой, как map() в питоне, но и С++ другой язык.

    Тоже +1. Просто люблю плюсы и шаблоны, а тут вот пишут такое:

    Остается только надеяться, что однажды можно будет в C(D?) программе написать:
    for item in some_list:
    do_something(item)

  16. bialix

    Товарыш koder вышел на тропу войны??? Ховайся хлопцы.
    (Всем жарко, не только вам, так что иногда стоит сливать кипяток.)

    В целом я написал несерьезную и в чем-то провокационную статью. Признаюсь.
    Перечитайте ее название.

    Про сконс можно говорить долго и нудно. Начал его пользовать два года назад и периодически читал список рассылки (как user, так и dev). Вы привели ссылки на обсуждения 2004 года. Я читал в 2005-2006 годах. Проблемы все еще оставались. И в 2007 году они никуда не делись. У сконса вообще очень жесткая политика разработки, может последний год что-то поменялось, не знаю.

    Пока что для меня панацеей от медлительности питона было и остается использование быстрой машины.

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

  17. koder

    Ничего личного )), просто после рекламы mkdir’a зашел на очередной портал
    программистов и нашел всех старых знакомых, коих обсуждаю уже лет 5.
    И про скорость питон программ и про то что кому не нравится, до полного набора не
    хватает только “Почему я никогда не променяю Java/C++/C#/Lisp/…… на питон”.
    Но в этой статье хоть оригинальность проявлена. Вот с этой фразой я
    полностью согласен

    Но где-то здесь, мне кажется, таится фундаментальная ошибка. Подвох. Обман.

    . Тепьрь я понимаю что периодически у меня подобные ощущения были, только буквами не оформлялись. Это когда после профилировки иногда приходится самые pythonic куски переписывать ((.

  18. motus

    koder:

    если бы у себя в прототипе я написал
    template<class X,class Y> int for_each(X &,const Y &){...}
    то вместо Y уже нельзя было-бы подставить ф-цию.

    хмм.. что-то я не врубился. почему указатель на функцию нельзя передать по конст ссылке? должно работать.

  19. koder

    gcc 4.1 не компилит. Основная причина – для функции нет способа указать что она не меняет static переменные(или что у нее таких нет) и соотв. непонятно изменится ли ее внутренние состояние.

  20. koder

    s/внутренние/внутреннее/

  21. AndrewK

    Насчет использования Bazaar – то Mercurial побыстрее будет. В разы.
    http://weblogs.mozillazine.org/jst/archives/2006/11/vcs_performance.html

  22. motus

    koder:

    gcc 4.1 не компилит. Основная причина – для функции нет способа указать что она не меняет static переменные(или что у нее таких нет) и соотв. непонятно изменится ли ее внутренние состояние.

    у меня (gcc 4.1.2) все компилится:

    template<class T>
    static void foo( const T& func ) { std::cout << func() << std::endl; }
     
    int main()
    {
        foo(getpid);
    }

    в случае с foo(getpid) T имеет тип указателя на функцию, т.е. в foo() передается ссылка на константный указатель. поскльку внутри foo() мы этот указатель не меняем, все должно быть ок. статические переменные тут ни при чем.

  23. koder

    Приведенный код gcc точно не скомпилит – в конце main return пропущен.

    #include <iostream>
    extern int getpid();
    template<class T>
    static void foo( const T& func ) { std::cout << func() << std::endl; }

    int main()
    {
    foo(getpid);
    return 1;
    }

    test.cpp: In function `int main()’:
    test.cpp:7: no matching function for call to `foo(int (&)())’

    Тестил под mingw
    $gcc –version
    gcc (GCC) 3.2.3 (mingw special 20030504-1)
    Copyright (C) 2002 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions. There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  24. motus

    1) по стандарту, return в конце main() не обязателен, так что все скомпилится;

    2) проблема в gcc 3.2 и 3.3 – в остальных версиях (я проверял еще 4.1, 3.4 и 2.95) все работает, как и должно.

  25. dreamer

    ) начали с петон а закочели плюсами ))) Психи нах, а не девелоперы, смешно! )

Оставить комментарий

Указать свой сайт могут только зарегистрированные пользователи. Регистрация или вход.

Архив

Добавить статью

Станьте автором нашего сайта!

Какие материалы подходят для публикации? — Такие.

Присылайте статьи на editors@developers.org.ua.

Подробнее.

Популярные теги

Все теги

Комментарии

Последние комментарии

интернет магазин бытовая техника магазин Laptoper