20 Март, 2010

Программисты и железо

Не так давно у нас на работе (Виктор, Игорь, Олег привет вам) состоялась дискуссия на тему: должны ли программисты знать как работает железо на котором выполняются их программы? И я еще раз убедился в том, что большинство программистов придерживаются мнения: "железо само по себе, а я сам по себе". Точка зрения вполне ожидаемая и ничего принципиально неправильного в ней нет, но я хотел бы "копнуть глубже".

Вообще, мне кажется вопрос "стоит ли программистам изучать железо" в чем-то похож на вопрос "стоит ли программистам изучать математику", — ответ неоднозначен. Существует множество вопросов, ответы на которые могут повлиять на окончательное решение: в какой предметной области вы работаете, насколько эти конкретные знания ценны для вас и т.д. Это вопрос инвестиций и прибыли. В данном случае под инвестициями подразумевается в первую очередь ваше свободное время, а под прибылью — профессиональные навыки и знания, которые позволят вам более эффективно делать вашу работу. Тогда вопрос сводится к следующему: чем изучение железа может помочь нам программистам делать свою работу лучше?

Мы с вами живем в эпоху высокоуровневых языков. Программисты большинства отраслей с успехом забыли про unmanaged языки, не говоря уже об ассемблерных вставках. В этом есть свои преимущества. Во-первых, это позволило нам программистам быть более эффективными. При равных доступных ресурсах теперь мы можем решать более сложные задачи. Во-вторых, не требуя от программистов "погружения в железо", мы позволяем им специализироваться в своей области, а также увеличить их количество за счет более короткой learning curve. Последнее впрочем имеет и свои негативные последствия, но я не буду сейчас акцентировать на них внимание.

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

Почему стоит изучать?

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

Возьмите хотя бы возросший интерес, к actor'ам. В общем и целом actor'ы представляют собой модель кооперативной многозадачности. Если вы хорошо помните историю, то кооперативная многозадачность в широких масштабах последний раз "упоминалась" в начале 90-х. У нее есть один существующий минус — она не работает на маленьком количестве исполнителей. Когда у вас один процессор легко может случится так, что какая-либо задача оккупирует его и другие задачи не смогут выполнятся. Тем не менее, у кооперативной многозадачности есть плюсы которые заставили нас опять обратить свой взор на эту модель...

Дело в том, что основная проблема с которой сталкиваются современные модели распараллеливания (которые преимущественно основаны на потоках) — это context switch. Доступ к памяти не является random'ным, чтобы ни говорили разработчики железа. Latency доступа к памяти на современных платформах составляет сотни тактов процессора. За это время процессор может сделать много работы. Эту проблему сейчас адресуют довольно простым путем — кеш, размер которого уже достигает 2Mb и больше на ядро. Проблемы кеша вам уже должны быть известны, — они одни и те же, неважно говорим ли мы о CPU cache или о memcached. Как только вы получаете промах кеша, вы платите performance penalty. Именно cache miss'ы являются источником деградации производительности в случае высокого context switching'а. Об этом говорило очень много умных дядек.

Решение довольно очевидно. Не переключатся между задачами лишний раз, только после завершения всей задачи целиком. Здравствуй кооперативная многозадачность. Не верите мне, поверьте сотрудникам Яндекса. Не зря в Windows существуют fiber'ы.

Справедливости ради, следует заметить, что скорость не единственный (и лично для меня не главный) плюс модели actor'ов. Эта модель гораздо проще в понимании и тестировании чем традиционные thread-based приложения. Но интерес к этой модели начал появляться как раз в тот момент, когда традиционные способы увеличения производительности исчерпали себя и мы начали искать новые методы обеспечения роста. А это означает одну простую вещь — программные абстракции используемые нами меняются в том числе и под "давлением аппаратных факторов".

У каждого технического решения есть свои причины влияющие на его формирование. Не всегда эти причины лежат непосредственно в области программной инженерии. Знание аппаратных факторов дает программисту более полную картину того, почему мир в котором мы живем таков каков он есть. Это основная идея, которую на мой взгляд не обосновано игнорирует большинство программистов.

Никто не просит вас уметь программировать на ассемблере и разбираться в opcode'ах микропроцессора. Но осознание того как работает процессор и какие bottleneck'и есть у существующих аппаратных платформ может дать вам очень хороший теоретический background для решения многих задач и ответа на многие вопросы.

Root of all evil

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

Верная предпосылка, но абсолютно не рациональный вывод. Это не проблема знаний, это проблема человека использующего эти знания. Чувство меры и здравоумие ни в коей мере не должно вас покидать, какие бы знания вы не получали.

Tradeoffs

С другой стороны надо трезво оценивать свои возможности. Существует масса знаний/умений которые для программиста важнее чем знание железа. Вот, на мой взгляд, всего лишь некоторые из них (перечислено в произвольном порядке):

  • ОО анализ и проектирование (шаблоны/SOLID принципы);
  • анализ и построение алгоритмов;
  • классические структуры данных;
  • диагностика типичных проблемных ситуаций;
  • тестирование и поддержка legacy систем;
  • умение писать корректный многопоточный код, а также находить ошибки в многопоточном коде (светлое будущее с Clojure, Erlang, Scala, whatever еще не наступило);
  • функциональная декомпозиция;
  • автоматизация процесса разработки;
  • продолжите список...

Если вы чувствуете, что есть важные знания из области программной инженерии которые для вас на данный момент важнее чем знание железа, то выбор очевиден. В первую очередь мы должны развиваться в тех направлениях которые диктует нам наша сфера деятельности.

В итоге

Саморазвитие, как это ни странно, требует жертв. Иногда приходится тратить время на изучение вещей, изучать которые совсем не хочется. Лично для меня таким инструментом в свое время был git. Но, видимо, иногда для того чтобы стать лучше приходится "наступать своей песне на горло". Так что я верю, что рано или поздно, если вы хотите стать хорошим программистом, вам прийдется выйти из своего дома и посмотреть как живут ваши соседи.


5 comments:

  1. А какие знания о железе имеются в виду?

    ИМХО, достаточно базовых знаний, чтобы понять куда ветер дует. Например, я бы не стал тратить много времени на оптимизацию системы под random read, протестировав SSD. Или стал бы спускать мьютексы пониже, понимая, что через пару лет, ядер будет несколько сотен.

    Гораздо важнее, на мой взгляд, знать как работает OS, т.к. тема шире, подводных камней больше, да и железо она сильно скрывает. Взять тот же scheduler или особенности работы с ФС.

    ЗЫ: Я бы с список первым пунктом добавил изучение английского языка ;)

    ОтветитьУдалить
  2. Спасибо, кстати, за статью и интересные ссылки.

    ОтветитьУдалить
  3. Для меня такими знаниями являются: поведение связки CPU-память, bottleneck'и в SMP архитектуре, а также производительность IO подсистемы (SSD с этой точки зрения очень важное нововведение).

    Я не хочу агитировать за изучение конкретных тем. Смысл данной заметки скорее в том, что изучение смежных областей знаний тоже полезно (изучение операционных систем тоже, но это уже тема совсем другого разговора :) ).

    P.S. по поводу английского это да. Для меня это настолько само собой разумеющееся, что я даже не подумал об этом :)

    ОтветитьУдалить
  4. АнонимныйMar 29, 2010 07:32 AM

    Привет, Денис! Сорри, увидел твой пост и не смог удержаться и не ответить :)

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

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

    На мой взгляд, обычному прикладному программисту достаточно быть в мэйнстриме программных технологий, ведь программные технологии как правило подстраиваются под аппаратные, а не наоборот. Стоит ли инвестировать свое время в изучение аппаратых технологий про которые даже не известно будут ли они использоваться в ближайшем будующем? Стоит ли программисту применить свои знания, о тонкостях распределения памяти операционной системой или полжиться на компилятор, ведь вполне может оказаться, что сэкономив пару мегабайт оперативки он окажет медвежью услугу всей команде когда, например, возникнет задача портировать код на другую платформу? Согласись, что в повседневной практике современный программист гораздо чаще сталкивается с задачей классификации и декомпозиции чем с проблемой "деградации производительности в случае высокого context switching'а". И на мой взгляд способность решать задачу именно первые две задачи отличает хорошего программиста.

    Вот в общем-то моё мнение, но хотелось бы подчеркнуть, что всё вышесказанное относится только к прикладным разработчикам, и не относится к системным программистам, архитекторам, проектировщикам ПО.

    А на вполне резонный вопрос - а какой программист не хочет стать архитектором, могу только ответить, что эта тема достойна отдельной дискуссии. В свое время на мое отношение к этому вопросу очень сильно повлиял пост Майкла Платта, мнению которого для меня очень авторитетно. http://blogs.technet.com/michael_platt/archive/2004/02/05/67908.aspx ok

    ОтветитьУдалить
  5. @Анонимный

    День добрый! Спасибо за комментарий и очень хорошую ссылку, и не стоило "удерживаться" :)

    Скажу честно, под этим углом я не смотрел на проблему, - я вообще не очень склонен разделять программистов и архитекторов. Нет, я не считаю что в этом нет смысла. Смысл есть. Моя точка зрения скорее всего связана с тем (и это вполне естественно), что я работаю в относительно не большом коллективе и нам пока не нужны архитекторы в виде отдельной должности. Но, если провести разделение между прикладными программистами и архитекторами, то конечно погружаться в железо всем не стоит. Тем более что у прикладных программистов действительно есть более важные вещи для изучения (и я об этом явно упомянул в заметке). Поэтому, мне остается только согласится с вами :)

    ОтветитьУдалить