태그 보관물: applied-theory

applied-theory

계산 복잡성에 대한 지식이없는 프로그래머가 문제가 되는가? 강사에게 보여주었습니다. 간단한 관찰 후, 그는

나는 대학에서 운동을 배정 받았다. 나는 그것을 집으로 가져 와서 그것을 해결하기 위해 알고리즘을 프로그래밍하려고 시도했다. 그래프와 관련이 있고 연결된 구성 요소를 찾는 것이라고 생각한다.

그런 다음 마음에 들어온 가장 사소한 것을 강사에게 보여주었습니다. 간단한 관찰 후, 그는 내 솔루션의 런타임 복잡성이 불가피하고 더 효율적인 것을 보여주었습니다. 그리고 계산 복잡성에 대해 전혀 모르는 프로그래머의 전통이 있습니다 (저는 그 중 하나였습니다). 프로그래머가 계산 복잡성에 대해 전혀 모른다면 문제가 있습니까?



답변

예, 계산 복잡성에 대해 아는 것이 진지한 프로그래머에게는 필수입니다. 거대한 데이터 세트를 다루지 않는 한 복잡성을 모르는 것이 좋지만 심각한 문제를 해결하는 프로그램을 작성하려면 필요합니다.

특정 경우에 연결된 구성 요소를 찾는 예는 최대 노드의 그래프에서 작동했을 수 있습니다 . 그러나 100.000 개의 노드로 그래프를 시도하면 강사의 알고리즘이 1 초 안에이를 관리했을 것입니다.하지만 알고리즘은 (복잡도가 얼마나 나쁜지에 따라) 1 시간, 1 일 또는 심지어 1 영원을 가질 것입니다.

100

100.000

알고리즘 과정에서 학생들이 흔히 저지르는 실수는 다음과 같이 배열을 반복하는 것입니다.

while array not empty
    examine first element of array
    remove first element from array

이것은 가장 아름다운 코드는 아니지만 복잡한 프로그램에서는 프로그래머가 알지 못하는 채 표시 될 수 있습니다. 자,이 프로그램의 문제점은 무엇입니까?

요소 의 데이터 세트에서 실행한다고 가정하십시오 . 다음 프로그램과 비교할 때 이전 프로그램은 50.000 느리게 실행됩니다 .

100.000

50.000
while array not empty
    examine last element of array
    remove last element from array

프로그램을 배 빠르게 실행하는 데 필요한 지식을 보유 하는 것이 프로그래머에게는 중요한 일 이라는 데 동의합니다 . 두 프로그램의 차이점을 이해하려면 복잡성 이론에 대한 기본 지식과 프로그래밍중인 언어의 특정 사항에 대한 지식이 필요합니다.

50.000

의사 코드 언어에서 “배열에서 요소 제거”는 모든 요소를 ​​왼쪽에서 한 위치에서 제거되는 요소의 오른쪽으로 이동합니다. 이렇게하면 마지막 요소를 제거하는 작업이 가되므로 하나의 요소와 만 상호 작용하면됩니다. 첫 번째 요소 를 제거하려면 첫 번째 요소를 제거하기 위해 다른 모든 n 1 요소를 한 위치 왼쪽으로 이동해야하므로 O ( n ) 입니다.

O(1)

O(n)

n−1

복잡성의 매우 기본적인 운동은 첫 번째 프로그램이 수행 할 것임을 증명하는 것입니다 두 번째 프로그램은n 개의작업만 사용하지만 2 n2개의작업입니다. 당신이에 연결하면N=100.000당신은 하나 개의 프로그램이 대폭보다 효율적인 다른보다 볼 수 있습니다.

12엔2

n=100.000

이것은 단지 장난감의 예이지만 두 프로그램의 차이점을 말하기 위해서는 복잡성에 대한 기본 이해가 이미 필요합니다. 실제로이 실수가있는보다 복잡한 프로그램을 디버깅 / 최적화하려고하면 찾기에 더 많은 이해가 필요합니다 버그가 어디에 있는지. 이런 식으로 배열에서 요소를 제거하는 것과 같은 실수는 코드의 추상화에 의해 잘 숨겨 질 수 있습니다.

복잡성을 잘 이해하면 두 가지 접근 방식을 비교하여 문제를 해결할 때 도움이됩니다. 연결된 구성 요소 문제를 스스로 해결하기위한 두 가지 다른 접근 방식을 생각해 냈다고 가정 해 봅시다. 구성 요소 간을 결정하려면 복잡성을 추정하고 더 나은 방법을 선택할 수 있다면 매우 유용 할 것입니다.


답변

이것은 Tom van der Zanden의 답변에 대한 반박입니다 .

문제는 대부분 50.000 배 느리다는 것입니다 (물론 Google에서 작업하지 않는 한).

작업에 마이크로 초가 걸리거나 N이 특정 임계 값 (요즘 수행되는 코딩의 많은 부분)을 초과하지 않으면 결코 중요하지 않습니다. 이러한 경우 계산 복잡성을 생각하면 시간과 돈을 낭비하게됩니다.

계산 복잡도는 왜 무언가가 느리게 진행되거나 크기가 심하게 저하 될 수 있는지, 그리고 그것을 개선하는 방법을 이해하는 도구이지만, 대부분의 시간은 완전히 지나친 것입니다.

나는 5 년 이상 동안 전문 프로그래머였으며 루프 O (M * N) 내에서 루핑 할 때 계산 복잡도에 대해 생각할 필요가 없었습니다. 왜냐하면 항상 작업이 실제로 빠르거나 M과 N이 너무 빠르기 때문입니다. 작은.

프로그래밍 작업을하는 사람에게는 훨씬 중요하고 일반적으로 사용되며 이해하기 어려운 것들이 있습니다 (스레딩 및 프로파일 링은 성능 영역에서 좋은 예입니다).

물론 계산 복잡도를 이해하지 않고는 결코 할 수없는 일이 있지만 (예 : 사전에서 아나그램 찾기) 대부분의 경우 필요하지 않습니다.


답변

저는 약 30 년 동안 계약자 및 직원으로 일하면서 소프트웨어를 개발해 왔으며 꽤 성공적이었습니다. 나의 첫 번째 언어는 기본 이었지만 저의 힘을 잃은 상자에서 적절한 속도를 내도록 기계 언어를 빠르게 가르쳤습니다. 몇 년 동안 프로파일 러에서 많은 시간을 보냈으며 빠르고 메모리 효율적인 최적화 코드 생성에 대해 많은 것을 배웠습니다.

말할 것도없이, 나는 스스로 가르친다. 몇 년 전에 인터뷰를 시작하기 전까지는 O 표기법을 접한 적이 없습니다. 인터뷰 중에는 전문 작업에서 절대 나오지 않습니다. 그래서 나는 인터뷰에서 그 질문을 다루기 위해 기초를 배워야했습니다.

악보를 읽을 수없는 재즈 뮤지션인 것 같습니다. 난 여전히 잘 재생할 수 있습니다. 나는 해시 테이블 (해시 테이블이 이미 발명되었다는 것을 알기 전에 해시 테이블을 발명했다)과 다른 중요한 데이터 구조에 대해 알고 있으며 학교에서 가르치지 않는 몇 가지 트릭을 알 수도 있습니다. 그러나 나는이 직업에서 성공하기 위해서는 인디에 가거나 인터뷰 중에 물어볼 질문에 대한 답을 배워야한다는 것이 진실이라고 생각합니다.

덧붙여서, 나는 가장 최근에 프론트 엔드 웹 개발자 역할을 위해 인터뷰했습니다. 그들은 답이 계산의 복잡성과 대수에 대한 지식을 필요로하는 질문을 나에게 물었다. 나는 20 년 전의 수학에 대해 다소 정확하게 대답하기에 충분한 수학을 기억했지만 약간 혼란 스러웠습니다. 프런트 엔드 개발에서 로그를 사용할 필요가 없었습니다.

당신에게 행운을 빕니다!


답변

질문은 매우 주관적이므로 답이 달려 있다고 생각합니다 .

소량의 데이터로 작업하는 경우에는 그다지 중요하지 않습니다. 이 경우 일반적으로 언어의 표준 라이브러리와 같은 것을 사용하는 것이 좋습니다.

그러나 많은 양의 데이터를 처리하거나 다른 이유로 프로그램이 빠르다고 주장하는 경우 계산 복잡성을 이해해야합니다. 그렇지 않으면 어떻게 문제를 해결해야하는지 또는 얼마나 빨리 해결할 수 있는지 어떻게 알 수 있습니까? 그러나 이론을 이해하는 것만으로는 정말 좋은 프로그래머가 되기에는 충분하지 않습니다. 매우 빠른 코드를 생성하려면 머신 작동 방식 (캐시, 메모리 레이아웃, 명령어 세트) 및 컴파일러의 기능 (컴파일러가 최선을 다하지만 완벽하지는 않음)을 이해해야합니다.

간단히 말해서, 복잡성을 이해하면 분명히 더 나은 프로그래머가 될 것입니다.


답변

중요한 알고리즘을 개발하는 사람이 알고리즘의 복잡성을 이해하지 못하면 문제가됩니다. 알고리즘 사용자는 일반적으로 성능 특성이 우수한 구현 품질에 의존합니다. 복잡성이 알고리즘의 성능 특성에 유일하게 기여하는 것은 아니지만 중요한 것입니다. 알고리즘의 복잡성을 이해하지 못하는 사람은 유용한 성능 특성을 가진 알고리즘을 개발할 가능성이 적습니다.

사용 가능한 알고리즘의 품질이 좋다고 가정하면 알고리즘 사용자에게는 별 문제가되지 않습니다. 이는 중요하고 잘 정의 된 표준 라이브러리가있는 언어를 사용하는 개발자에게 해당됩니다. 요구에 맞는 알고리즘을 선택하는 방법 만 알고 있으면됩니다. 복잡성은 종종 선택하는 기준 중 하나이기 때문에 라이브러리 내에서 사용 가능한 특정 유형의 여러 알고리즘 (예 : 정렬)이있는 경우 문제가 발생합니다. 복잡성을 이해하지 못하는 개발자는 자신의 작업에 효과적인 알고리즘을 선택하는 기초를 이해할 수 없습니다.

그런 다음 비 알고리즘 문제에 초점을 맞추는 개발자가 있습니다 (더 나은 설명을 원함). 예를 들어, 직관적 인 사용자 인터페이스 개발에 중점을 둘 수 있습니다. 이러한 개발자는 종종 알고리즘이나 복잡한 것에 대해 걱정할 필요가 없지만 라이브러리 나 다른 코드를 고품질로 개발할 수도 있습니다.


답변

작업하는 데이터의 양이 아니라 개발하는 프로그램의 종류에 따라 다릅니다.

개념적 복잡성에 대해 모르는 프로그래머에게 전화를 걸어 보자.

멍청한 프로그래머는 다음을 수행 할 수 있습니다.

  • 빅 데이터 데이터베이스 개발-데이터베이스 내부의 작동 방식을 알 필요가 없으며 데이터베이스 개발에 대한 규칙 만 있으면됩니다. 그는 다음과 같은 것을 알고 있습니다. 인덱싱해야 할 것, … 데이터에서 중복성을 만드는 것이 더 나은 곳, 그렇지 않은 곳 …
  • 게임 만들기-그는 일부 게임 엔진의 작동 방식을 연구하고 패러다임을 따르기 만하면됩니다. 게임과 컴퓨터 그래픽은 매우 큰 데이터 문제입니다. 단일 사진 / 프레임의 경우 1920 * 1080 * 32bit = cca 7.9MB를 고려하십시오 … @ 60 FPS 최소 475MB / s입니다. 불필요한 전체 화면 그림 사본 하나만 초당 약 500MB의 메모리 처리량이 낭비된다는 점을 고려하십시오. 그러나 그는 엔진 만 사용하기 때문에 신경 쓰지 않아도됩니다!

멍청한 프로그래머는하지 말아야합니다 :

  • 예를 들어, 작은 데이터는 컴파일 시간보다 느리기 때문에 개발 중에 부적절한 솔루션에 눈에 띄는 영향을 미치지 않습니다. 예를 들어 0.5 초보적인 프로그래머 관점에서 볼 때 하나의 간단한 프로그램에 대해 sec는이 프로그램을 초당 20 회 실행하는 서버 서버를 고려하십시오. 그 부하를 견딜 수 있으려면 10cores가 필요합니다!
  • 임베디드 장치를위한 프로그램 개발 임베디드 장치는 작은 데이터로 작동하지만 중복 작업으로 인해 불필요한 전력 소비가 발생하기 때문에 가능한 한 효율적이어야합니다.

따라서 기술을 사용하고 싶을 때 noobish 프로그래머는 괜찮습니다. 따라서 새로운 솔루션, 맞춤형 기술 등을 개발할 때는 멍청한 프로그래머를 고용하지 않는 것이 좋습니다.

그러나 회사가 새로운 기술을 개발하지 않으면 이미 만들어진 기술 만 사용합니다. 숙련되고 재능있는 프로그래머를 고용하는 것은 재능의 낭비 일 것입니다. 새로운 기술을 사용하고 싶지 않고 이미 만들어진 프레임 워크를 사용하여 고객 아이디어를 디자인과 프로그램에 넣는 것이 좋으면 시간을 낭비하고 필요없는 것을 배우는 것은 시간 낭비입니다. 그것이 취미이고 논리적 인 도전을 좋아한다면.


답변

나는 여기에 답을 쓰는 것을 다소 주저하지만 여러 다른 사람들에 대한 nitpicking을 발견했기 때문에 (내 의견 중 일부는 채팅으로 이동했습니다), 여기 내가 어떻게 보는지입니다 …

컴퓨팅에는 많은 것들에 대한 수준의 지식이 있습니다 (이 용어로 나는 컴퓨터 과학과 정보 기술의 통합을 의미합니다). 계산 복잡도는 분명히 광대 한 분야이며 (OptP가 무엇인지 아비 보울-비누 아 정리가 말하는가?) 깊이도 인정합니다. CS 학위를 가진 대부분의 사람들은 연구에 참여하는 전문가의 증거를 만들 수 없습니다 계산 복잡성의 간행물.

그러한 문제에 필요한 지식과 기술 / 능력의 수준은 자신이 무엇을 하는가에 달려 있습니다. 완전히 단서가없는 O (

엔2

) 정렬은 때때로 느린 프로그램의 주요 원인이라고 말하지만 [인용 필요] 2003 SIGCSE 논문에 따르면 “삽입 정렬은 표준 Java 및 C ++ 라이브러리에서 작은 (하위) 배열을 정렬하는 데 사용됩니다.” 반대로, 점근 적 의미가 무엇인지 이해하지 못하는 사람 (컴퓨팅 복잡도는 그러한 척도 임)이 조기에 최적화 되는 것이 때때로 프로그래밍 실무에서 문제가됩니다. 그러나 계산 복잡성이 중요한 시점을 아는 것은 적어도 학부 수준에서 이에 대한 힌트가 필요한 이유입니다.

C에서 성능에 민감한 코드를 구현하고 성능에 영향을 미치지 않는 다소 일반적인 관행 (자바 세계 외부)과 계산 복잡성 개념을 적용하는 시점과 안전하게 무시할 수있는 시점을 알고있는 상황을 솔직히 비교합니다. 파이썬 등의 것들. (제쳐두고, 이것은 Julia 토크에서 “표준 타협” 이라고 불렀습니다 .) 성능에 대해 생각할 필요가 없을 때 알면 프로그래밍 시간을 절약 할 수 있습니다. 이는 상당히 귀중한 상품이기도합니다.

또 하나의 요점은 계산의 복잡성을 알면 프로그램 최적화에 자동으로 도움이되지 않는다는 것입니다. 캐시 지역성, [때로는] 파이프 라이닝, 오늘날의 병렬 / 멀티 코어 프로그래밍과 같은 더 많은 아키텍처 관련 사항을 이해해야합니다. 후자는 자체 복잡성 이론과 실제 고려 사항을 모두 가지고 있습니다. A로부터 후자의 맛 2013 SOSP 용지 모든 잠금 방식은 “우리는 지속적으로 모든 대상 아키텍처 또는 워크로드에, 다른 하나를 능가하는 성능을 고려 아홉 개 잠금 방식의 명성. 없음의 15 분있다. 엄밀히 말하면, 최적하는을 추구하는 하드웨어 플랫폼과 예상 작업량에 따라 잠금 알고리즘을 선택해야합니다. “