대규모 소프트웨어 프로젝트에서 실제로 복잡성을 측정하는 방법은 무엇입니까?


11

대학에서는 알고리즘 과정에서 해시 테이블 또는 빠른 정렬과 같이 실제로 사용되는 다양한 간단한 알고리즘의 복잡성을 정확하게 계산하는 방법을 배웁니다.

그러나 이제는 큰 소프트웨어 프로젝트에서 더 빠르게 만들고 싶을 때 개별 조각을 살펴 보는 것입니다. 더 빠른 해시 테이블로 대체 할 수있는 중첩 루프가 거의 없습니다. 더 멋진 기술이지만 전체 파이프 라인의 복잡성을 계산하지는 않습니다.

그렇게 할 방법이 있습니까? 아니면 실제로 사람들이 빠른 알고리즘을 사용하여 "로컬로"의존하여 응용 프로그램을 전체적으로 전체적으로 고려하는 대신 전체 응용 프로그램을 더 빠르게 만드는가?

(자체적으로 매우 빠른 것으로 알려진 많은 수의 알고리즘을 쌓아 올리면 전체적으로 빠른 응용 프로그램으로 끝납니다.)

많은 알고리즘이 입력 데이터에서 상호 작용하고 작업하는 곳에서 다른 사람이 작성한 큰 프로젝트의 속도를 높이는 작업을 수행하고 있기 때문에 단일 알고리즘에 대한 영향이 더 빠르다는 것은 확실하지 않습니다. 전체 응용 프로그램.


1) 개선 할 요점을 찾으려면 테스트 방법이 필요합니다. 벤치 마크 테스트, 내구성 테스트, 동적 테스트 (각 구성 요소의 메모리 / CPU 메트릭 모니터링) 2) 개선 할 점을 찾은 후 그 점의 근본 원인을 찾을 수 있습니다. 3) 근본 원인을 해결하고 정확성을 유지하는 솔루션을 찾으십시오.
overexchange

당신은 점 1에서 언급이 시험에 대한 몇 가지 도구가 필요합니다
overexchange

1
Big O 분석은 알고리즘의 수행 방식을 알려주지 않습니다. 그것은 성능이 방법을 알려줍니다 규모n증가합니다.
존 우

답변:


5

대규모 소프트웨어 프로젝트는 여러 가지 구성 요소로 구성되며 모두 병목 현상이 아닙니다. 이와는 정반대로 : 저 성능이 문제가되는 거의 모든 프로그램에서 파레토 원칙이 적용되었습니다. 코드의 20 % 미만을 최적화하면 성능 향상의 80 % 이상을 달성 할 수 있습니다. 숫자가 종종 95 %에서 5 % 더 많았다 고 생각합니다.

따라서 개별 조각을 살펴 보는 것이 가장 좋은 방법입니다. 즉 (에 설명 된대로 프로파일 데이비드 아르노의 대답 ) 당신이 당신에게 "벅에 대한 가장 큰 강타"을 줄 것이다 최적화 코드의 5 %를 언급 식별하는 데 도움이 있기 때문에 괜찮습니다. "전체 응용 프로그램"을 최적화하면 과도하게 엔지니어링 할 위험이 있으며, 95 %까지 10 배까지 최적화하더라도 측정 가능한 효과가없는 경우가 많습니다. 또한 O (N ^ 3) 단계를 필요로하는 간단한 알고리즘이 N (O (N log (N))을 필요로하는 복잡한 알고리즘보다 여전히 빠를 수 있기 때문에 프로파일 링은 어떤 가상 알고리즘 복잡성 추정보다 더 많은 방법을 알려줍니다. 충분히 작습니다.

프로파일 링 후 핫스팟이 밝혀지면이를 최적화 할 수 있습니다. 물론 "핫스팟"은 한 줄 또는 두 줄의 코드보다 클 수 있습니다. 때로는 더 빠른 구성을 위해 전체 구성 요소를 교체해야하지만 더 큰 프로그램에서는 여전히 코드 기반의 작은 부분이됩니다. .

일반적인 최적화 기술에는 다음이 포함됩니다.

  • 알고리즘 및 데이터 구조 사용 개선

  • 전자의 미세 조정

  • 일부 실제 핫스팟에서의 미세 최적화

  • 어셈블리 코드 또는 CUDA를 사용하여 중요 섹션 레코딩

이 기술들은 서로 다른 추상화 수준에서 작동하고 있으며, 그 중 일부는 구성 요소를 다른 것보다 "전체적으로"볼 수 있습니다. 따라서 "우리가하는 모든 것은 개별 조각을 보는 것"의 의미에 따라 다릅니다. 미세 최적화 만 염두에두면 "우리"가 그에 대해서만 작동한다는 데 동의하지 않습니다. 그러나 분리 된 부품 또는 구성 요소에 이러한 전체 최적화를 적용하려는 경우 "우리"가 올바른 부품을 사용하고있는 것보다 기대에 의문을 제기해야합니다.


13

시도되고 테스트 된 표준 방법은 코드프로파일 링하는 것입니다 . 실행중인 시스템의 동적 분석을 수행하여 타이밍, 메모리 사용량 등을 측정 한 다음 결과를 분석하여 성능 병목 현상을 찾습니다.

그런 다음 이러한 병목 현상을 실험적으로 다시 작성하고 결과를 한 번 더 프로파일 링하여 속도 증가, 메모리 사용 감소 등이 달성되었는지 확인합니다. 그런 다음 수용 가능한 성능 향상을 얻을 때까지이 프로세스를 반복합니다.


1
이것은 성능 문제를 해결하므로 우리는 그렇게하지만 원래의 질문에 답하지는 않습니다. 특히 최악의 경우 시간이나 공간의 복잡성은 정적 프로그램 분석 도구를 사용하는 것이 가장 좋습니다. 성능 테스트는 특정 시나리오에 적합하지만 최악의 상황에 대해서는 알려주지 않습니다.
Frank Hileman 16:24에

3
@FrankHileman 저는 여기서 중요한 점은 성능이 실질적인 관심사이며 실제로 만 측정 할 수 있다는 것입니다. 수학 (알고리즘)을 사용하여 찾은 경우에도 소프트웨어의 병목 현상을 찾기 위해 수학을 사용하지 않습니다.
와일드 카드

관련 메모에서 옛날 슬라이드 쇼 프레젠테이션 (유리 슬라이드)에는 사용할 빛의 밝기를 결정하기 위해 랜턴 슬라이드의 평균 밀도를 수학적으로 계산하는 방법에 대한 전체적인 기술이있었습니다. 완전히 쓸모없는 : 사진이 잘 보이지 않으면 더 밝게 빛납니다!
와일드 카드

@Wildcard 성능은 런타임시에만 측정 할 수 있지만 정적으로 예측할 수 있습니다. 데이터 구조를 잘못 선택하면 성능 테스트에서 성능이 현명 해 보이지만 정적 분석에서 예측할 수있는 엣지 사례에서는 비참하게 실패 할 수 있습니다. 이것이 일반적인 데이터 구조에 대한 최악의 경우 복잡도 분석을 보는 것과 같은 이유입니다.
Frank Hileman 17시

@Wildcard : 당신은 맞지만 Frank는이 게시물이 질문에 대답하지 않는다는 것이 매우 정확합니다.
Doc Brown

3

다른 답변은 정확하고 지침을 제공하지만 단계가 빠진 것 같습니다. 현재 작업중인 복잡한 시스템에서 시스템을 구성하는 다양한 구성 요소를 이해하는 것이 왜 느린 이유를 이해하는 데 중요합니다.

첫 번째 단계는 세부 아키텍처 다이어그램을 보거나 직접 작성하는 것입니다. 소프트웨어의 어떤 구성 요소에 의해 수행되는 단계와 각 단계에 걸리는 시간을 파악하십시오.

또한 구성 요소가 서로 어떻게 상호 작용하는지 파악하십시오. 이것은 모든 차이를 만들 수 있습니다.

예를 들어, 두 구성 요소 사이의 인터페이스가 첫 번째 구성 요소에 의해 작성된 IEnumerable을 전달하는 두 번째 구성 요소에 의해 열거 된 C #의 코드를 보았습니다. C #에서는 컨텍스트 전환이 필요하며 특정 상황에서는 비용이 많이들 수 있습니다. 이를 해결해도 알고리즘에는 영향을 미치지 않습니다. 간단한 .ToList ()는 다음 단계에서이 문제를 해결하기 전에 결과를 수집해야합니다.

고려해야 할 또 다른 사항은 코드를 실행하는 시스템에 미치는 영향입니다. 하드웨어 상호 작용은 복잡한 시스템에서 분명히 한 요소가 될 수 있습니다. 디스크 IO, 대용량 메모리 할당 및 네트워크 IO를 찾으십시오. 때로는 시스템을 조정하거나 하드웨어를 교체하여 더 효율적으로 해결할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.