Нужно ли понимать, что происходит на аппаратном уровне, чтобы быть хорошим программистом?

24

Я программист-самоучка, на всякий случай, если на этот вопрос ответят в CS 101. Я выучил и использовал много языков, в основном для личного пользования, но иногда и для профессиональных вещей.

Кажется, что я всегда сталкиваюсь с одной и той же стеной, когда сталкиваюсь с проблемами программирования. Например, я только что задал вопрос на другом форуме о том, как обрабатывать указатель на массив, который был возвращен функцией. Сначала я думаю, что просто не знаю правильную технику, которую разработчики C ++ создали, чтобы справиться с ситуацией. Но из ответов и обсуждений, которые следуют, я вижу, что я действительно не понимаю, что происходит, когда что-то «возвращается».

Насколько глубокий уровень понимания процесса программирования должен достичь хороший программист?

Гай
источник
3
Мой совет: изучите какую-нибудь сборку x86 (DOS или иначе). Затем научитесь читать некоторые из выходных данных ассемблера о некоторых маленьких кусочках кода C. Задавайте вопросы, если вы не понимаете вывод. Повторение. Это заставит вас понять, что происходит на уровне процессора
Earlz
Earlz - Вы имеете в виду, что я должен научиться программировать с использованием набора инструкций x86? Это «уровень процессора»?
Bev
Работа - спасибо, это было весело. Он на самом деле сделал несколько ошибок, правда, только к вашему сведению.
Bev

Ответы:

33

Нет. Никто не понимает, что происходит на аппаратном уровне.

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

Но опять же...

Да. Я имею в виду, вам не нужно понимать, что на самом деле происходит внутри лука, но это очень помогает иметь мысленную модель того, как выглядит внутренняя часть типичного лука. Может быть, не самая глубокая часть, где у вас есть вентили, состоящие из транзисторов и тому подобного, или следующий слой или два, где у вас есть микрокод, часы, единицы декодирования команд и т. Д. Однако следующие слои, где вы У меня есть регистры, стек и куча. Это самые глубокие уровни, на которые вы оказываете большое влияние на происходящее: компилятор переводит ваш код в инструкции, которые выполняются на этом уровне, и, если вы хотите, вы обычно можете выполнить эти инструкции и выяснить, что «на самом деле» происходит.

Большинство опытных программистов имеют слегка сказочную версию этих слоев в своей голове. Они помогают вам понять, о чем говорит компилятор, когда он сообщает, что произошла «ошибка недопустимого адреса» или «ошибка переполнения стека» или что-то в этом роде.

Если вам интересно, почитайте книгу по компьютерной архитектуре. Это даже не должно быть особенно новой книгой - цифровые компьютеры долгое время работали примерно одинаково. Чем больше вы узнаете о внутренней части лука, тем больше вы будете поражены тем, что все это работает! Изучение (приблизительно) того, что происходит на нижних уровнях, делает программирование менее загадочным и, так или иначе, более волшебным. И действительно, веселее.

Еще одна вещь, на которую вы можете обратить внимание, это встроенный лук. Я имею в виду встроенные системы. Есть ряд встроенных платформ, которые довольно просты в использовании: Arduino и BASIC Stamp - два примера. Это в основном небольшие микропроцессоры с множеством встроенных функций. Вы можете думать о них как о луке с меньшим количеством слоев, чем у вашего обычного настольного ПК, так что можно получить довольно полное представление о том, что происходит во всей системе, от аппаратного обеспечения до программного обеспечения.

Калеб
источник
2
Спасибо. Это в основном отвечает на мой вопрос. Я EE, который разработал дизайн регистров, сумматоров, мультиплексоров и т. Д. На уровне микросхем (т.е. на уровне транзисторов), поэтому я получаю самый низкий уровень (если мы не говорим о квантовой механике). Я также могу использовать языки, которые я знаю достаточно хорошо. У меня просто огромный пробел на среднем уровне (стек, куча), где вы говорите, что компилятор выполняет свою работу. Поскольку, как вы говорите, я хочу, чтобы мой опыт программирования был "менее загадочным и ... более волшебным". Кажется, мне следует изучить уровни, которые мне пока неизвестны.
Гэв
@bev: В этом случае вам действительно стоит проверить платформу вроде Arduino.
Калеб
Извините, что скучно, но я проверил Arduino, и я не могу понять, как его использование поможет мне понять, как компилятор по-разному относится к указателям и массивам. Что я не вижу?
Гэв
@bev: Если вы просто хотите узнать, как вызываются функции, вы можете потратить 30 минут, читая об этом, и все будет готово. Если вы хотите лучше понять, как все работает вместе, это будет проще всего с небольшой системой. Это лучший способ получить весь лук в голову сразу. AVR, семейство микросхем, на которых основан Arduino, - это удобная, универсальная, простая в использовании система с набором инструкций, который достаточно мал, чтобы учиться без особых проблем.
Калеб
Ах хорошо. Домашняя страница немного мутная по этому аспекту их продуктов. Я посмотрю снова.
Bev
10

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

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

Лорен Печтель
источник
Лорен - да! Спасибо за простую правду. Теперь мне нужно найти лучший способ узнать, что компиляторы c ++ делают со своими типами данных. Кстати, как EE, я знаю, что это не аппаратный уровень буквально. Я просто не знал, как вы, CS, фанаты, называете это. (Все еще не в этом отношении. Уровень компилятора?)
Bev
Кстати - память топает?
Гэв
@Bev: Вы только что подтвердили мою точку зрения - если вы даже не знаете, что такое стамп памяти, у вас будет ужасное время, чтобы найти ошибку из-за одной ошибки. Стоп памяти - это когда что-то записывается в место, которое ему не предназначено, и стирает (топает) все, что там произошло. Если вам повезло, все, что вы ударили, сразу же стало жизненно важным и, по крайней мере, оно взрывается. Если вам не повезло, программа просто продолжает работать с некоторыми пробелами в своих данных.
Лорен Печтел
благодарю за разъяснение. Это также показывает мне, сколько я не знаю, поскольку, насколько я знаю, я просто записываю в кучу или в стек, без более точного управления.
Гэв
@Bev: проблема возникает, когда ты пишешь куда-то, а ты не думаешь, что пишешь. У вас есть что-то в стеке, и вы делаете указатель на это. Вы выходите из рутины - элемент исчезает, указатель - нет. Что происходит, когда вы пишете в этот указатель ?? Или у вас есть массив из 100 элементов - что происходит, когда вы пишете в элемент № 200?
Лорен Печтел
6

Понимание памяти программ! = Понимание оборудования

Понимание иерархии памяти == Понимание оборудования


Чтобы ответить на ваш общий вопрос: это зависит. Это не помешает понять аппаратное обеспечение, но понимание этого не поможет во всех случаях.

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

Если вам любопытно узнать о проблемах производительности, связанных с порядком, в котором вы обращаетесь к памяти, СЕЙЧАС вы выиграете от понимания аппаратного обеспечения, иерархии памяти, ошибок кэширования, сбоев страниц и всего великолепного качества, которое исходит от оборудования.

riwalk
источник
Stargazer - я еще не дошел до того, что могу беспокоиться о проблемах с производительностью. Надеюсь, скоро. Спасибо за ваши комментарии.
Гэв
5

Если вы действительно решили узнать немного ассемблера, вероятно , вы должны узнать что - то вроде 6502 ассемблера на Commodore 64 (эмулировать, конечно), или 68000 на Amiga.

Вы можете получить представление о Commodore 64 здесь ...

http://thepiratebay.org/torrent/4609238/Tag3-Saal2-Slot16_00--ID2874-the_ultimate_commodore_64_talk-Main

Классическая книга «все, что нужно знать» описана здесь ...

http://reprog.wordpress.com/2010/03/12/programming-books-part-3-programming-the-commodore-64/

Вы можете, вероятно, найти сканирование PDF, если вы посмотрите вокруг.

IMO, 6502 легче, чем Z80, и 68000 легче, чем 8086 - более регулярные наборы команд и т. Д.

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

Особое преимущество 6502 на C64 заключается в том, что он не только прост с центральным процессором, но и с некоторыми очень простыми аппаратными средствами. Раньше мне было очень весело играть с музыкальным чипом SID.

Так что - это, вероятно, стоящее упражнение, если вы не тратите на него слишком много времени. Я изучил ассемблер 6502 как мой второй язык, когда мне было около 14 лет, сразу после Commodore Basic. Но в основном он получает очень простую рабочую модель, чтобы вы могли добавлять к ней более сложные идеи с минимумом недопонимания.

Некоторые полезные вещи, которые вы можете узнать, работая в ассемблере ...

  • Как работает регистр процессора.
  • Как работает адресация памяти, включая косвенное обращение.
  • Как работает процессорный стек
  • Как работает побитовая логика.
  • Как процессор управляет устройствами ввода / вывода.
  • Как прерывает работу.

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

Но насколько именно сейчас полезно знать большинство этих вещей, это сложный вопрос.

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

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

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

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

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

Это моя любимая книга для этого ...

http://dickgrune.com/Books/MCD_1st_Edition/

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

Steve314
источник
Стив - вау. Я почти потерял дар речи с полнотой и направленностью вашего ответа на мой вопрос. Большое спасибо, что нашли время, чтобы написать все это. Я обязательно приму ваши предложения.
Гэв
1
Я хотел бы предположить, что ассемблер PDP-11 немного приятнее для изучения, чем все другие упомянутые. Все остальные учат ограничениям, вызванным более ограниченными аппаратными ресурсами и / или более ограниченным дизайном и продуманностью оборудования. Что-то вроде одного из слишком распространенного семейства 8051 учит, насколько странной может быть модель программирования на таком ограниченном оборудовании (например, когда Стив упоминает о разных адресных пространствах).
Грег А. Вудс
@ Грег - Боюсь, мне никогда не приходилось играть с PDP-11. Ни 8051 - я некоторое время занимался встроенной работой, но для этого использовался чип семейства 8096. Я только что посмотрел здесь, хотя - интересно. Я слышал об архитектуре Гарварда раньше, но я понятия не имел, что есть что-то подобное, которое было очень популярно и все еще используется.
Steve314
4

Двадцать лет назад это было важно, но не так много сейчас - между программным обеспечением и современным оборудованием гораздо больше уровней абстракции.

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

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

Том Кларксон
источник
Да, вы правы, меня больше заботит компилятор. Кроме того, спасибо за ваше предложение о нескольких потоках, нескольких ядрах и т. Д. Он только что вошел в мой файл заметок toLearn.
Bev
Многопоточность @bev проста в освоении, просто не делайте этого, если вам действительно не нужно, и даже тогда не делайте этого. больше проблем, чем стоит в моем опыте.
Скит
@Skeith - спасибо за совет. Я буду иметь это в виду.
бев
4

Это очень помогает узнать и понять абстракцию, представленную оборудованием, и немного общей идеи о том, как создается эта иллюзия, - но попытка действительно понять, как на самом деле работает современное оборудование, - это огромный объем работы, из которого вы ' Скорее всего, увидеть только минимальный доход.

Если вы простите небольшую утечку: это напоминает мне кое-что, что я заметил несколько лет назад. Десятилетия назад (вплоть до конца 1970-х годов или около того) большинство людей думали, что компьютеры на шаг не дотягивают до волшебства - на них почти не влияют законы физики, они способны на всевозможные вещи, которые не имеют реального смысла, и так далее. В то время я потратил немало времени, пытаясь (в основном безуспешно) убедить людей, что нет, они не были волшебниками. Это были действительно довольно обычные машины, которые делали ограниченное количество вещей очень быстро и надежно, но в остальном были чрезвычайно обыденными.

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

Мой взгляд на компьютеры тоже изменился. Я посещал Hot Chips, а до этого Форум по микропроцессорам восходит к середине 1990-х или около того. Я, вероятно, знаю больше о микропроцессорном оборудовании, чем, по крайней мере, 99% программистов - и, зная, что я делаю, я скажу следующее: они больше не обычные. Они же почти нарушают законы физики. Я провел много низкоуровневых тестов, и я могу сказать это наверняка: преодолеть иллюзию, создаваемую процессором, и перейти к уровню демонстрации того, как на самом деле работает оборудование, зачастую невероятно сложно. Я хотел бы опубликовать фотографию одной из наших установок с компьютером, скрытым под кабелями не менее чем из 4 логических анализаторов, просто чтобы правильно измерить один аспект того, как работает кэширование на современном процессоре (не говоря уже о некоторых по-настоящему привередливых программах, чтобы гарантировать, что то, что мы измерили, было именно тем, что делал процессор, и ничего больше).

Джерри Гроб
источник
Джерри - спасибо за ваши комментарии. Будучи EE, я чувствую себя более комфортно с уровнем транзистора, чем с некоторыми более высокими уровнями абстракции. Мне просто интересно, что мне нужно знать, чтобы стать хорошим программистом на C ++.
Гэв
Эта картина звучит интересно. Почему вы не можете опубликовать это?
Мейсон Уилер
@Bev: Вам не нужно ничего знать на уровне транзисторов, чтобы быть хорошим программистом. Эти абстракции существуют по какой-то причине, и вы почти всегда можете считать что-либо на уровне абстракции ниже уровня машинного кода / сборки полностью нерелевантным и просто предполагать, что это работает.
Мейсон Уилер
@MasonWheeler: Я взял его там, где раньше работал, но, поскольку я там больше не работаю, получить доступ к нему, вероятно, будет немного сложнее (вероятно, не невозможно - я ухожу в хороших отношениях, но даже так. ..)
Джерри Коффин
1

Разные языки работают на разных уровнях абстракции от аппаратного обеспечения. C и C ++ очень низкого уровня. Языки сценариев, с другой стороны, требуют, чтобы вы знали меньше об основных деталях.

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

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

Скотт Уитлок
источник
Скотт - под «довольно хорошим пониманием того, как работает современный процессор ...», вы имеете в виду, как работает цифровая логика (например, как работают карты Карно, таблицы истинности, вентили AND / OR / NOR / XOR)? или вы имеете ввиду какие ресурсы компилятор использует напрямую (т.е. регистрирует)?
Bev
Знать больше - это хорошо. Реальный трюк, однако, заключается в том, чтобы знать, какое «больше» даст максимальную отдачу. Например, знание сроков выполнения команд не принесет особой пользы, когда почти невозможно предсказать, какие инструкции будет использовать ваш компилятор. Изучение, как использовать профилировщик, вероятно, даст намного лучшее соотношение цены и выгоды.
Steve314
1
@bev - Нет, я не думаю, что тебе нужно спускаться до уровня ворот. Если вы просто знали основную архитектуру (память, шина, процессор), как она загружает инструкцию, выполняет ее, сохраняет результат и т. Д., Вы, вероятно, в порядке. Вы также должны понимать, как компилятор распределяет пространство памяти программы, включая то, как она использует стек и кучу.
Скотт Уитлок
@ ScottWhitlock - Спасибо - это всего лишь конкретные рекомендации, которые я искал.
Гэв
0

Я хотел бы добавить пункт об общем дизайне языков высокого уровня, таких как C.

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

Документ DMR Переносимость программ на C и системы UNIX - первое, что я помню, чтобы обсудить (абстрактную) модель машины для C.

Я думаю, что статья DMR об истории и развитии C также чрезвычайно полезна для демонстрации того, как реальное аппаратное обеспечение влияет на дизайн языка, и, возможно, также является примером раннего проектирования языка программирования: Разработка языка C

Грег А. Вудс
источник
Поскольку вы новичок здесь, вы, кажется, думаете, что это форум, это, безусловно, не так. Ваши ответы на вопрос не должны быть точкой, которую вы добавляете, их следует относить к комментариям, а ответ должен пытаться быть исчерпывающим ответом непосредственно на вопрос. Тем не менее, вы делаете хорошую точку зрения, и это очень важно для информации по теме, возможно, если бы вы могли поставить несколько строк в этом ответе на вопрос непосредственно вместе с этим объяснением, было бы здорово. Классная информация, которой вы делитесь здесь. Добро пожаловать в Программисты!
Джимми Хоффа
комментарии не являются версионными и не постоянными и поэтому бесполезны для добавления к набору ответов. Большинство постеров также склонны игнорировать использование комментариев для обновления своих ответов, и большинство ответов не помечены как ответы "сообщества вики" и поэтому не могут быть отредактированы другими пользователями таким образом, чтобы сохранить некоторую атрибуцию для последующих авторов , Кроме того, этот конкретный вопрос вызвал настоящую дискуссию, и нравится нам это или нет, так идут некоторые из этих вещей. Попытка втиснуть каждый вклад в одну форму - главный недостаток концепции стека обмена.
Грег А. Вудс
и, между прочим, я действительно ответил, неявно, на один истинный вопрос ОП: у человека должно быть достаточно понимания аппаратных средств, чтобы можно было смоделировать абстрактную машину в основе разработки языка.
Грег А. Вудс