Мой любимый неторопливый питон
Александр БельченкоОпубликовано 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.
Понравилась статья? Подпишись на обновления по RSS/E-mail

По поводу
for item in some_list:
в последней версии 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) – это решает массу проблем
(если они есть, конечно, но чаще всего они таки есть).
А вот Вы лично и сходите в список рассылки тех же docutils и scons и поучите их уму-разуму. А то ребята который год не могут правильный алгоритм выбрать.
Если честно — все написанное Вами настолько тривиально и избито… Однако проблема все равно имеет место быть. И будет. И пока что решается только одним путем — использования самого быстрого компьютера из имеющихся.
Я далекий от питона человек, но, учитывая написанное выше, меня удивляет, почему Гугл с их гуглоподобными объемами данных пишут на этом языке (вернее, в том числе на этом).
предлагаю пререписать на ассемблере
Як варіант відповіді — Python використовується на «вищому» рівні для поєднання компонент, написаних на C/C++.
Хоча, дійсно, існують і інші мови програмування високого рівня з швидкими інтерпретаторами/компіляторами.
PS. : колись Yahoo! відкрила свій власний документ про переваги переходу з YahooScript на PHP.
Она на С++ пишется на раз и без всякого boost
уставSTL, двоечники – std::for_each() уже сто лет как стандарт. заодно рекомендую обратить внимание, что в STL конец контейнера передается отдельным параметром, и что функциональный объект передается по значению. (вопрос “зачем” оставляем читателям в качестве упражнения)насколько я знаю, в гугле питона не так много, как все считают.. пару лет назад была презентация на эту тему: python at google.. гугл, кстати, активно использует SWIG – странно, что про него никто не вспомнил.
еще вроде популярный вариант – Boost::Python, но я его не использовал никогда.
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
Медленно работают? А есть причины полагать что можно быстрее? Может просто действительно данных очень много?
Есть причины полагать, что да. Эта причины — программы-конкуренты.
Но данных действительно очень много. Порой.
В общем еще одна вещь, от которой спасает только быстрая машина — это очень медленный старт самого интерпретатора Питона. Вы пробовали когда-нибудь запустить Питон на Целероне 300 МГц? Вот когда узнаешь, что значит слово “терпение”
Низкая скорость питона имеет место быть. Однако программы написанные на Java/.NET тоже медленны (по сравнению с C++). Это – расплата за вкусности и кросплатфоренность. И действительно, бороться с этим можно только переводя части кода на более быстрые языки. И конечно использовать только к подходящим задачам.
Бо “Нема на то ради” (с)
Если это не вычислительные задачи (типа перемножения матриц), то в среднем С# отстаёт от С процентов на 20. Языки же вроде питона и руби проигрывают в разы!
bialix:
docutils не использовал, а производительность scons вполне приемлемая. В любом
случае компилятор съедает основную часть времени(в случае с docutils могу
сказать что крайне низкая скорость работы LaTeX почему-то никого не волнует).
Ваша статья затрагивает их только как пример, а дальше идет рассуждение на тему
какой питон тормоз и что нет от этого спасения так что и советы не относились к
ним конкретно, а имели общий характер.
Безусловно, но написанное в заметке ему явно противоречит.
А именно это:
, на что и был ответ, что нет, не все нужно переписывать(кроме некоторых исключений), в основном можно обойтись малой кровью(примеров масса – cheetah один из них).
Программы типа scons безусловно не расчитаны на Celeron 300, там Вас только
make и спасет. Я предлагаю Вам привести пример быстрых систем, подобных по
возможностям к scons(желательно не тормозящих на указанной машине).
Для примера – jam(boost) тормозит если и меньше, то несущественно.
И AFAIK обладает существенно меньшим количеством возможностей.
motus:
Приведен __ПРИМЕР__ наиболее близкий к питоновскому map(function,object).
В stl отдельным параметром передается не только конец контейнера, но и его
начало(собственно контейнер вообще не передается).
Теперь предлагаю motus поупражнять знание питона и подумать почему я передал
функциональный объект по ссылке(намекаю – это было сделано специально).
И, кстати, этот пример замечательно работает не только к функторами но и с
функциями.
В догонку.
Просмотр списка рассылки 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) – там тоже ничего про общую
оптимизацию, а только улучшение алгоритма отслеживания измененных файлов.
koder:
хм. ну тогда можно было и поближе найти, как мне кажется. питоновский map(), насколько я понимаю, возвращает новый список – это ближе к std::copy() или std::transform() + insert_iterator, но никак не к for_each(), тем более в том виде, в каком вы его написали.
ну это и ежу понятно. впрочем, если придираться к словам, то стандартные алгоритмы вообще не знают ни про контейнеры, ни про их “начало” и “конец”. пример – тот же std::for_each() + std::istream_iterator.
я питон знаю плохо, но упражняться люблю. my guess – это просто потому, что в питоне все передается по ссылке. теперь, пожалуйста, скажите правильный ответ.
впрочем, я другое хотел сказать с самого начала: в каждом языке есть свои паттерны и идиомы, и нечего в С++ лепить свой for_each(), если уже есть STL. он не такой, как map() в питоне, но и С++ другой язык.
surprise, surprise – передача по значению и стандартные алгоритмы прекрасно работают с обычными С функциями, напр.
std::transform(str.begin(), str.end(), str.begin(), toupper);Да, с map я описался, он тут совсем не причем, приведен пример соотв. требуемому
for i in storage:func(i)
Придиратся к словам начали Вы, это был просто ответ в том-же духе.
+1. Так-же потому что иногда объект накапливает определенную информацию при прохождении массива, что используется уже после цикла/map.
Я и не говорил что они не могут, но вот если бы у себя в прототипе я написал
template<class X,class Y> int for_each(X &,const Y &){….}
то вместо Y уже нельзя было-бы подставить ф-цию. Это был ответ на
, насколько я понял именно
на невозможность использования ф-ций с const X & и намекалось.
Тоже +1. Просто люблю плюсы и шаблоны, а тут вот пишут такое:
Товарыш koder вышел на тропу войны??? Ховайся хлопцы.
(Всем жарко, не только вам, так что иногда стоит сливать кипяток.)
В целом я написал несерьезную и в чем-то провокационную статью. Признаюсь.
Перечитайте ее название.
Про сконс можно говорить долго и нудно. Начал его пользовать два года назад и периодически читал список рассылки (как user, так и dev). Вы привели ссылки на обсуждения 2004 года. Я читал в 2005-2006 годах. Проблемы все еще оставались. И в 2007 году они никуда не делись. У сконса вообще очень жесткая политика разработки, может последний год что-то поменялось, не знаю.
Пока что для меня панацеей от медлительности питона было и остается использование быстрой машины.
В дискуссии про С++ влазить не буду, потому что я не люблю этот язык.
Ничего личного )), просто после рекламы mkdir’a зашел на очередной портал
программистов и нашел всех старых знакомых, коих обсуждаю уже лет 5.
И про скорость питон программ и про то что кому не нравится, до полного набора не
хватает только “Почему я никогда не променяю Java/C++/C#/Lisp/…… на питон”.
Но в этой статье хоть оригинальность проявлена. Вот с этой фразой я
полностью согласен
. Тепьрь я понимаю что периодически у меня подобные ощущения были, только буквами не оформлялись. Это когда после профилировки иногда приходится самые pythonic куски переписывать ((.
koder:
хмм.. что-то я не врубился. почему указатель на функцию нельзя передать по конст ссылке? должно работать.
gcc 4.1 не компилит. Основная причина – для функции нет способа указать что она не меняет static переменные(или что у нее таких нет) и соотв. непонятно изменится ли ее внутренние состояние.
s/внутренние/внутреннее/
Насчет использования Bazaar – то Mercurial побыстрее будет. В разы.
http://weblogs.mozillazine.org/jst/archives/2006/11/vcs_performance.html
koder:
у меня (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() мы этот указатель не меняем, все должно быть ок. статические переменные тут ни при чем.
Приведенный код 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.
1) по стандарту, return в конце main() не обязателен, так что все скомпилится;
2) проблема в gcc 3.2 и 3.3 – в остальных версиях (я проверял еще 4.1, 3.4 и 2.95) все работает, как и должно.
) начали с петон а закочели плюсами ))) Психи нах, а не девелоперы, смешно! )