Я получил задание в моем университете. Я взял его домой и попытался запрограммировать алгоритм для его решения, это было что-то, связанное с графиками, поиск связанных компонентов, я думаю.
Затем я сделал самую тривиальную вещь, которая пришла мне в голову, а затем показала моему лектору. После непродолжительного наблюдения он понял, что сложность моего решения во время выполнения была неизменной, и показал что-то более эффективное. И есть традиция программистов, которые не имеют представления о том, что такое вычислительная сложность (я был одним из них), поэтому проблема в том, что программист не имеет понятия о том, что такое вычислительная сложность?
algorithms
algorithm-analysis
education
applied-theory
Билли Рубина
источник
источник
Ответы:
Да, я бы сказал, что знание чего-либо о сложности вычислений является обязательным условием для любого серьезного программиста. Пока вы не имеете дело с огромными наборами данных, у вас все будет в порядке, не зная сложности, но если вы хотите написать программу, которая решает серьезные проблемы, она вам нужна.
В вашем конкретном случае ваш пример поиска связанных компонентов мог бы работать для графиков, скажем, до узлов. Однако, если вы попробуете граф с 100 000 узлов, то алгоритм вашего лектора, вероятно, справится с этим за 1 секунду, в то время как ваш алгоритм (в зависимости от степени сложности) займет 1 час, 1 день или даже 1 вечность.100 100,000
Несколько распространенная ошибка, которую студенты делают в нашем курсе алгоритмов, состоит в том, чтобы перебрать массив следующим образом:
Это может быть не самый красивый код, но в сложной программе что-то вроде этого может появиться без ведома программиста. Теперь, в чем проблема с этой программой?
Предположим, мы запускаем его на наборе данных из элементов. По сравнению со следующей программой прежняя программа будет работать на 50 000 медленнее.100,000 +50,000
Я надеюсь, что вы согласны с тем, что знание программиста для того, чтобы ваша программа работала в раз быстрее, вероятно, важно для программиста. Понимание различий между этими двумя программами требует некоторых базовых знаний о теории сложности и некоторых особенностей языка, на котором вы программируете.+50,000
В моем языке псевдокода «удаление элемента из массива» сдвигает все элементы справа от удаляемого элемента на одну позицию слева. Это делает удаление последнего элемента операцией поскольку для этого нам нужно взаимодействовать только с 1 элементом. Удаление первого элемента - это O ( n ), поскольку для удаления первого элемента нам нужно сместить все остальные n - 1 элементов на одну позицию влево.O ( 1 ) O ( n ) n - 1
Очень базовое упражнение по сложности, чтобы доказать, что первая программа будет делать операций, в то время как вторая программа использует толькоnопераций. Если вы подключитеn=100.000,вы увидите, что одна программа значительно эффективнее другой.12N2 N n = 100 000
Это всего лишь игрушечный пример, но он уже требует базового понимания сложности, чтобы понять разницу между двумя программами, и если вы на самом деле пытаетесь отладить / оптимизировать более сложную программу, которая имеет эту ошибку, требуется еще большее понимание, чтобы найти где ошибка. Потому что такая ошибка, как удаление элемента из массива таким способом, может быть очень хорошо скрыта абстракциями в коде.
Хорошее понимание сложности также помогает при сравнении двух подходов к решению проблемы. Предположим, что вы придумали два разных подхода к решению проблемы со связанными компонентами самостоятельно: для того, чтобы решить между ними, было бы очень полезно, если бы вы могли (быстро) оценить их сложность и выбрать лучший.
источник
"So long as you are not dealing with huge data sets you will be fine not knowing complexity"
Это часто правда, но не всегда так. Например,O(n!)
алгоритм не будет жизнеспособным даже для относительно небольших наборов данных. Если вы используетеO(n!)
алгоритм, который вы могли бы использовать,O(n^2)
ваша программа будет исполняться в 36 288 раз дольше при размере данных 10 . При размере данных 20 вы просматриваете 2,4 операции квинтиллиона.Это опровержение ответа Тома ван дер Зандена , в котором говорится, что это необходимо.
Дело в том, что в 50.000 раз медленнее не имеет значения (если, конечно, вы не работаете в Google).
Если операция, которую вы выполняете, занимает микросекунду или если ваш N никогда не превышает определенного порога (большая часть кодирования, выполняемого в настоящее время), это НИКОГДА не будет иметь значения. В этих случаях размышления о сложности вычислений заставят вас терять время (и, скорее всего, деньги).
Вычислительная сложность - это инструмент, позволяющий понять, почему что-то может быть медленным или плохо масштабируемым, и как его улучшить, но большую часть времени это полное излишество.
Я являюсь профессиональным программистом уже более пяти лет, и я никогда не обнаруживал необходимости думать о сложности вычислений при циклическом цикле внутри цикла O (M * N), потому что всегда операция действительно быстрая, а M и N таковы. маленький.
Для тех, кто выполняет задания по программированию, есть гораздо более важные, обычно используемые и более сложные вещи (многопоточность и профилирование - хорошие примеры в области производительности).
Конечно, есть некоторые вещи, которые вы никогда не сможете сделать без понимания вычислительной сложности (например: поиск анаграмм в словаре), но в большинстве случаев вам это не нужно.
источник
Я занимаюсь разработкой программного обеспечения около тридцати лет, работая как подрядчиком, так и сотрудником, и я довольно преуспел в этом. Моим первым языком был BASIC, но я быстро выучил машинный язык, чтобы получить приличную скорость из своей коробки с недостаточной мощностью. За эти годы я провел много времени в профилировщиках и многое узнал о создании быстрого оптимизированного кода с эффективным использованием памяти.
Независимо от того, я самоучка. Я никогда не сталкивался с обозначением O, пока не начал брать интервью несколько лет назад. Это никогда не всплывало в моей профессиональной работе за исключением интервью. Поэтому я должен был изучить основы, чтобы справиться с этим вопросом в интервью.
Я чувствую себя джазовым музыкантом, который не умеет читать ноты. Я все еще могу играть просто отлично. Я знаю о хеш-таблицах (черт возьми, я изобрел хеш-таблицы до того, как узнал, что они уже были изобретены) и о других важных структурах данных, и я мог бы даже знать некоторые приемы, которые они не учат в школе. Но я думаю, что правда в том, что если вы хотите преуспеть в этой профессии, вам нужно будет либо заняться независимым бизнесом, либо узнать ответы на вопросы, которые они зададут во время интервью.
Между прочим, я недавно брал интервью для роли веб-разработчика интерфейса. Они задали мне вопрос, где ответ требовал знания вычислительной сложности и логарифмов. Мне удалось вспомнить достаточно математики двадцать лет назад, чтобы ответить на нее более или менее правильно, но это было немного неприятно. Мне никогда не приходилось использовать логарифмы при разработке внешнего интерфейса.
Удачи тебе!
источник
Вопрос довольно субъективный, поэтому я думаю, что ответ зависит от него .
Это не имеет большого значения, если вы работаете с небольшими объемами данных. В этих случаях обычно хорошо использовать то, что предлагает стандартная библиотека вашего языка.
Однако, когда вы работаете с большими объемами данных или по какой-то другой причине настаиваете, что ваша программа работает быстро, вы должны понимать сложность вычислений. Если вы этого не сделаете, как вы узнаете, как решить проблему или как быстро ее можно решить? Но понимания только теории недостаточно, чтобы стать действительно хорошим программистом. Я полагаю, что для создания чрезвычайно быстрого кода вы также должны понимать, как, например, работает ваша машина (кеши, структура памяти, набор команд) и что делает ваш компилятор (компиляторы делают все возможное, но не совершенны).
Короче говоря, я думаю, что понимание сложности явно делает вас лучшим программистом.
источник
Это, конечно, проблема, если кто-то, кто разрабатывает важные алгоритмы, не понимает сложности алгоритма. Пользователи алгоритма обычно полагаются на хорошее качество реализации, которое имеет хорошие характеристики производительности. Хотя сложность не является единственным фактором, влияющим на характеристики производительности алгоритма, она имеет большое значение. Тот, кто не понимает сложности алгоритма, с меньшей вероятностью будет разрабатывать алгоритмы с полезными характеристиками производительности.
Это не проблема для пользователей алгоритма, если предположить, что доступные алгоритмы имеют хорошее качество. Это верно для разработчиков, которые используют языки, которые имеют значительную, хорошо определенную, стандартную библиотеку - им просто нужно знать, как выбрать алгоритм, который соответствует их потребностям. Проблема заключается в том, что в библиотеке есть несколько алгоритмов некоторого типа (скажем, сортировки), поскольку сложность часто является одним из критериев выбора между ними. Разработчик, который не понимает сложности, не может понять основы выбора эффективного алгоритма для своей задачи.
Тогда есть разработчики, которые сосредотачиваются (не имея лучшего описания) на неалгоритмических проблемах. Например, они могут сосредоточиться на разработке интуитивно понятных пользовательских интерфейсов. Таким разработчикам часто не нужно беспокоиться о сложности алгоритма, хотя, опять же, они могут полагаться на библиотеки или другой код, разрабатываемый с высоким качеством.
источник
Это зависит, но не от количества данных, с которыми вы работаете, а от того, какую работу вы выполняете, программ, которые вы разрабатываете.
Давайте назовем программиста, который не знает о концептуальной сложности нубийским программистом.
Нубистский программист может сделать:
Нубистский программист не должен делать:
Итак, программист Noobish хорошо, когда вы хотите просто использовать технологии. Поэтому, когда речь заходит о разработке новых решений, нестандартных технологий и т. Д. Тогда лучше нанимать нубийских программистов.
Однако, если компания не разрабатывает новые технологии, просто использует уже созданные. Было бы напрасной тратой нанять опытного и талантливого программиста. То же самое относится и к тому, что если вы не хотите работать над новыми технологиями, и вы прекрасно вкладываете идеи клиентов в проекты и программы с использованием уже созданных фреймворков, то это пустая трата времени на изучение того, что вам никогда не понадобится, кроме если это твое хобби и тебе нравятся логические задачи.
источник
Я несколько не решаюсь написать ответ здесь, но так как я придираюсь к нескольким другим [некоторые мои комментарии были перенесены в чат], вот как я это вижу ...
Есть много уровней / степеней знаний для многих вещей в области вычислительной техники (и под этим термином я подразумеваю грубый союз информатики с информационными технологиями). Сложность вычислений, безусловно, является обширной областью (Знаете ли вы, что такое OptP? Или что говорит теорема Абитебул-Виану?), А также допускает большую глубину: большинство людей со степенью CS не могут предоставить экспертные доказательства, которые идут на исследования публикации в вычислительной сложности.
Я бы честно осмелился бы сравнить ситуацию с пониманием того, когда применять концепции вычислительной сложности (и со знанием того, когда их можно безопасно игнорировать), с довольно распространенной практикой (за пределами мира Java) реализации некоторого чувствительного к производительности кода на C и нечувствительного к производительности вещи в Python и т. д. (Кроме того, в разговоре Джулии это называлось «стандартным компромиссом» .) Знание того, когда вам не нужно думать о производительности, экономит ваше время программирования, что также является довольно ценным товаром.
И еще один момент заключается в том, что знание вычислительной сложности не поможет автоматически оптимизировать программы; вам нужно понимать больше вещей, связанных с архитектурой, таких как локальность кэша, [иногда] конвейерная обработка, а также параллельное / многоядерное программирование; последний имеет как собственную теорию сложности, так и практические соображения; вкус последнего из статьи SOSP 2013 года "Каждая схема блокировки имеет свои пятнадцать минут славы. Ни одна из девяти схем блокировки, которые мы рассматриваем, последовательно не превосходит любую другую на всех целевых архитектурах или рабочих нагрузках. Строго говоря, стремиться к оптимальности, Таким образом, алгоритм блокировки следует выбирать на основе аппаратной платформы и ожидаемой рабочей нагрузки ».
источник
Если вы не знаете, большой-O, вы должны научиться этому. Это не сложно, и это действительно полезно. Начните с поиска и сортировки.
Я заметил, что многие ответы и комментарии рекомендуют профилирование , и они почти всегда означают использование инструмента профилирования .
Проблема в том, что инструменты профилирования расположены по всей карте с точки зрения их эффективности для поиска того, что вам нужно для ускорения. Здесь я перечислил и объяснил неправильные представления, от которых страдают профилировщики.
В результате программы, если они больше академических упражнений, могут содержать спящих гигантов , которых не может показать даже самый лучший автоматический профилировщик. В этом посте показано несколько примеров того, как проблемы с производительностью могут скрываться от профилировщиков.
Но они не могут скрыться от этой техники.
источник