모듈 식 프로그래밍이 계산 시간에 영향을 줍니까?


19

누구나 코드를 모듈화해야한다고 말하지만 더 적지 않지만 더 큰 메소드보다는 더 많은 메소드 호출을 사용하면 덜 효율적이지 않습니까? 그 문제에 대한 Java, C 또는 C ++의 차이점은 무엇입니까?

특히 그룹에서 편집, 읽기 및 이해하기가 더 쉽다는 것을 알게되었습니다. 따라서 코드 시간 이점과 비교할 때 계산 시간 손실이 중요하지 않습니까?


2
문제는 더 어려운 유지 보수에 소요되는 시간을 절약하는 처리 시간에 걸리는 시간입니다. 이에 대한 대답은 전적으로 응용 프로그램에 따라 다릅니다.
— Blrfl

2
많은 좋은 질문은 전문가 경험을 바탕으로 어느 정도의 의견을 생성하지만이 질문에 대한 답변은 사실, 참조 또는 특정 전문 지식이 아닌 의견에 거의 근거한 경향이 있습니다.
— gnat

10
함수 또는 메소드 호출에 대한 계산 페널티가 너무 작아서 많은 함수 및 메소드 호출이있는 매우 큰 프로그램 에서도
— greyfade

1
@greyfade : 직접 점프의 경우에는 사실이지만 추가 간접 예측 점프는 예를 들어 프로그램의 총 실행 시간의 약 3 %가 소요될 수 있습니다 (최근에 확인한 프로그램의 수에 불과하지만 대표적이지 않았을 수도 있음). 지역에 따라 중요하거나 고려하지 않을 수도 있지만 차트에 등록했습니다 (물론 모듈화에 적어도 부분적으로 직교합니다).
— Maciej Piechotka

4
조기 최적화는 모든 악의 근원입니다. 선형 코드는 모듈 식 코드보다 약간 빠릅니다. 모듈 식 코드는 스파게티 코드보다 훨씬 빠릅니다. 전체적으로 매우 (매우) 철저한 프로젝트없이 선형 코드를 목표로한다면 스파게티 코드로 끝날 것입니다.
— SF.

답변:


46

그렇습니다.

컴퓨터는 두뇌와 비교할 수없는 속도로 작동하는 지칠 줄 모르고 거의 완벽한 실행 엔진입니다. 함수 호출이 프로그램의 실행 시간에 추가되는 상당한 시간이 있지만, 읽을 수없는 루틴을 풀어야 할 때 코드와 관련된 다음 사람의 두뇌에 필요한 추가 시간과 비교하면 아무것도 아닙니다 도에 시작 그것으로 작업하는 방법을 이해합니다. 농담에 대한 계산을 시도 할 수 있습니다. 코드를 한 번만 유지해야한다고 가정하고 누군가 코드를 이해하는 데 필요한 시간을 30 분만 추가 하면 됩니다 . 프로세서 클럭 속도를 계산하고 계산하십시오. 오프셋을 꿈꾸 려면 몇 번이나 코드를 실행 해야합니까?

요컨대, CPU를 불쌍히 여기는 것은 시간의 99.99 %를 완전히 잘못 인도 한 것입니다. 드문 경우로 프로파일 러를 사용하십시오. 마십시오 하지 당신이 그 사례를 발견 할 수 있다고 가정 - 당신은 할 수 없습니다.


2
나는 그것이 대부분 조기 최적화에 동의하지만, 시간에 대한 당신의 주장은 나쁘다고 생각합니다. 시간은 다른 상황에서 상대적이며 당신이 한 것처럼 단순히 계산할 수 없습니다.
— Honza Brabec

28
"CPU에서 동정을 취하는 것"이라는 표현은 +1인데, 이는 조기 최적화에서 잘못된 방향을 강조하기 때문입니다.
— Michael Borgwardt

4
관련성이 높음 : 컴퓨터는 일상적으로 얼마나 빠릅니까? "속도"에 대한 몇 가지 함수 호출을 피하기 위해 길을 떠나는 것은 평생 동안 총 1 분 동안 누군가를 구하는 길을 떠나는 것과 같습니다 . 한마디로 : 고려할 시간조차도 가치가 없습니다.
— BlueRaja-대니 Pflughoeft

7
많은 사람들이 잃어버린 것을 웅변 적으로 팔아서 +1하지만, CPU를 더 불쌍하게 만드는 균형에 가장 중요한 무게를 더하는 것을 잊었습니다. 한 번 유지 보수에 소비 된 돈과 시간을 무시하고; 1 초가 걸린다면 여전히 훨씬 더 교활한 싱크대가 있습니다. 버그 위험 . 나중에 유지 보수 담당자가 코드를 변경하는 것이 더 혼란스럽고 어려울수록 버그를 구현할 위험이 커져 사용자에게 불가피하게 막대한 비용이 발생할 수 있으며 버그는 후속 유지 보수를 유발할 수 있습니다 (이로 인해 발생할 수 있음) bugs ...)
— Jimmy Hoffa

저의 오래된 선생은 "너희가 조기에 최적화하고 있는지 아닌지를 생각하고 있다면 여기서 멈추십시오. 이것이 올바른 선택이라면, 당신은 그것을 알 것입니다."
— Ven

22

때에 따라 다르지.

느리게 진행되는 웹 프로그래밍, 즉 모든 것이 사람의 속도로 발생하는 웹 프로그래밍, 메소드 호출 프로그래밍, 메소드 호출 비용이 메소드가 수행하는 처리 비용과 비슷하거나 초과하는 경우는 중요하지 않습니다. .

임베디드 시스템 프로그래밍 및 고속 인터럽트에 대한 인터럽트 핸들러의 세계에서 가장 중요합니다. 해당 환경에서 일반적인 "메모리 액세스는 저렴"하고 "프로세서는 무한정 빠릅니다"라는 분류가 있습니다. 메인 프레임 객체 지향 프로그래머가 첫 번째 고속 인터럽트 핸들러를 작성할 때 어떤 일이 발생하는지 보았습니다. 예쁘지 않았습니다.

몇 년 전, 나는 실시간 FLIR 이미지에서 비 재귀적인 8 방향 연결성 얼룩 색소를 수행했습니다. 당시에는 적절한 프로세서였습니다. 첫 번째 시도는 서브 루틴 호출을 사용했으며 서브 루틴 호출 오버 헤드는 프로세서를 활성 상태로 만들었습니다. (4 호출 PER PIXEL x 프레임 당 64K 픽셀 x 초당 30 프레임 = 계산). 두 번째 시도는 서브 루틴을 가독성 손실없이 C 매크로로 변경했으며 모든 것이 장미였습니다.

당신은 당신이하고있는 일과 그것을 할 환경을 열심히 봐야합니다.


현대 프로그래밍 문제의 대부분은 많은 객체 지향, 메소드-행복한 코드를 처리하는 것이 가장 좋습니다. 임베디드 시스템 환경에있을 때 알게됩니다.
— Kevin-복원 모니카

4
+1이지만주의 사항 : 일반적으로 최적화 컴파일러가 사람보다 인라인, 루프 언 롤링 및 스칼라 및 벡터 최적화 작업을 더 잘 수행하는 경우가 많습니다. 프로그래머는 여전히 언어, 컴파일러 및 기계를 잘 알고 있어야 이것을 활용할 수 있으므로 마술이 아닙니다.
— detly

2
사실이지만 로직을 작성하고 프로파일 링 한 후 알고리즘에서 문제가있는 부분을 찾도록 코드를 최적화 했습니다. 성능을 위해 코딩하기 시작하지 않았지만 가독성을 위해 코딩을 시작했습니다. 매크로는 코드를 읽을 수있게 유지하는 데 도움이됩니다.
— Uwe Plonus

2
임베디드 시스템 프로그래밍도에 분명 올바른 코드를 작성하여 시작하고 해당 후 최적화 시작 필요한 경우 및 프로파일에 의해 인도로 . 그렇지 않으면 성능 / 코드 크기에 실제로 영향을 미치지 않고 소스를 이해하기 어렵게 만드는 많은 작업을 수행하기가 너무 쉽습니다.
— Donal Fellows

1
@detly : 그렇습니다. 현대의 컴파일러는 일반적으로 언어가 부과하는 한계 내에서 더 나은 작업을 수행 할 수 있습니다. 인간 프로그래머는 언어에 의해 부과 된 한계가 특정 상황에 적용 가능한지 여부를 알고 있습니다. 예를 들어, Cn 및 C ++ 컴파일러는 언어 표준에 따라 프로그래머가 매우 병적 인 일을하고 어쨌든 작동하는 코드를 생성 할 수 있도록 요구합니다. 프로그래머는 자신이 그런 일을하기에 충분히 미쳤거나 어리 석거나 모험적이지 않다는 것을 알 수 있으며,이 경우 안전하다는 것을 알고 있기 때문에 안전하지 않은 최적화를 수행 할 수 있습니다.
— John R. Strohm

11

우선 : 더 높은 언어의 프로그램은 기계가 아닌 사람이 읽을 수 있습니다.

그래서 그래서 프로그램을 작성하는 당신 을 이해합니다. 성능에 대해 생각하지 마십시오 (성능 문제가 심각하면 응용 프로그램을 프로파일 링하고 필요한 경우 성능을 향상 시키십시오).

메서드 나 함수를 호출하는 데 약간의 오버 헤드가 걸린다는 것은 사실이 중요하지 않습니다. 오늘날 컴파일러는 생성 된 코드가 대상 아키텍처에 효율적이되도록 효율적인 코드로 코드를 컴파일 할 수 있어야합니다. 효율적인 코드를 얻으려면 컴파일러의 최적화 스위치를 사용하십시오.


5
다른 사람들 이 이해할 수 있는 방식으로 프로그램을 작성해야한다고 말하고 싶습니다 .
— Bartlomiej Lewandowski

프로그램을 읽어야하는 첫 번째 사람은 개발자 자신입니다. 그게 내가 당신을 쓴 이유 입니다. 다른 사람이 프로그램을 읽을 수 있다면 좋지만 (내 눈에는) 필요하지 않습니다 (처음에는). 팀에서 일하는 경우 다른 사람도 프로그램을 이해해야하지만 내 의도는 사람이 컴퓨터가 아닌 프로그램을 읽어야한다는 것입니다.
— Uwe Plonus

5

일반적으로 큰 기능을 가지고 있고 더 작은 기능으로 나눌 때이 작은 기능은 인라인 의 유일한 단점 (동일한 명령을 너무 많이 반복)이 관련이 없기 때문에 인라인 됩니다. 즉, 코드가 하나의 큰 함수를 작성한 것처럼 작동합니다.

어떤 이유로 인라인되지 않았고 이것이 성능 문제가되는 경우 수동 인라인을 고려해야합니다. 모든 응용 프로그램이 내재 된 대기 시간이 큰 네트워크 CRUD 양식은 아닙니다.


2

계산 비용이 없을 것입니다. 일반적으로 지난 10-20 년 동안의 컴파일러 / JIT는 완벽하게 미세한 함수를 처리합니다. C / C ++의 경우 일반적으로 'inlinable'함수로 제한됩니다 (즉, 함수 정의는 컴파일하는 동안 컴파일러에서 사용할 수 있습니다. 즉, 동일한 파일의 헤더에 있음). LTO의 현재 기술은이를 극복합니다.

최적화에 시간을 소비해야하는 경우 작업중인 영역에 따라 다릅니다. 입력을 기다리는 대부분의 시간을 소비 한 '정상적인'응용 프로그램을 처리하는 경우 응용 프로그램이 '느낌'을 느끼지 않으면 최적화에 대해 걱정할 필요가 없습니다.

이러한 경우에도 미세 최적화를 수행하기 전에 많은 것에 집중해야합니다.

  • 문제는 어디에 있습니까? 소스 코드를 다르게 읽는 사람들은 일반적으로 핫스팟을 찾기가 어렵습니다. 우리는 작동 시간의 비율이 다르며 최신 프로세서 는 그렇지 않지만 순차적으로 수행합니다 .
  • 매번 계산이 필요합니까? 예를 들어, 수천 개 중 하나의 매개 변수를 변경하면 전체 모델 대신 영향을받는 부분 만 계산할 수 있습니다.
  • 최적의 알고리즘을 사용합니까? 에서 O(n)로 변경 O(log n)하면 미세 최적화를 통해 달성 할 수있는 것보다 훨씬 큰 영향을 줄 수 있습니다.
  • 적절한 구조를 사용하십니까? 당신은을 사용하는 말 List당신이 필요로 할 때 HashSet당신은 그래서 O(n)조회를 당신이 가진 수있을 때 O(1).
  • 병렬 처리를 효율적으로 사용합니까? 현재 휴대폰조차도 4 코어 이상을 가질 수 있으며 스레드 사용을 유혹 할 수도 있습니다. 그러나 동기화 비용이 들기 때문에 은총 알이 아닙니다 (문제가 메모리 바운드 인 경우 어쨌든 의미가 없음).

(소프트웨어가, HPC에 사용되는 내장하거나에서 사용되는 거의 수단 심지어 당신이 마이크로 최적화를 수행 할 필요가 있다고 결정했다면 매우 당신이 필요합니다 - 그렇지 않으면 유지 보수의 추가 비용이 컴퓨터 시간 비용을 극복하는 사람들의 많은 수의) 가속화하려는 핫스팟 (커널)을 식별합니다. 그러나 아마 당신은해야합니다 :

  1. 작업중인 플랫폼을 정확히 파악
  2. 작업중인 컴파일러와 수행 할 수있는 최적화 및 이러한 최적화를 가능하게하는 관용적 코드 작성 방법을 정확히 알고 있어야합니다.
  3. 메모리 액세스 패턴과 캐시에 얼마나 많은 양을 넣을 수 있는지 생각하십시오 (정확한 크기는 1 지점에서 알고 있음).
  4. 그런 다음 계산 바운드 인 경우 계산을 저장하기 위해 계산 재구성에 대해 생각하십시오.

마지막 말로. 일반적으로 메서드 호출과 관련된 유일한 문제는 분기 예측기에 의해 예측되지 않은 간접 점프 (가상 메서드)입니다 (불행히도 간접 점프는 어려운 경우입니다). 하나:

  • Java에는 많은 경우 클래스 유형을 예측할 수있는 JIT가 있으므로 사전에 점프 대상을 지정하므로 핫스팟에서는 많은 문제가 발생하지 않습니다.
  • C ++ 컴파일러는 종종 프로그램 분석을 수행하며 최소한 경우에 따라 컴파일 타임에 대상을 예측할 수 있습니다.
  • 두 경우 모두 목표가 예측 된 경우 인라인이 작동해야합니다. 컴파일러가 인라인 기회를 수행 할 수 없다면 우리도 할 수 없었습니다.

0

내 대답은 기존 답변에서 너무 많이 확장되지는 않지만 2 센트가 도움이 될 것 같습니다.

우선; 예, 모듈화의 경우 일반적으로 일정 수준의 실행 시간을 포기합니다. 어셈블리 코드로 모든 것을 작성하면 최고의 속도를 얻을 수 있습니다. 그건 ...

YouTube 알아요? 아마도 가장 높은 대역폭의 사이트일까요, 아니면 넷플릭스의 사이트일까요? 그들은 코드의 많은 부분을 파이썬으로 작성하는데, 이는 최고의 성능을 위해 개발되지 않은 고도로 모듈화 된 언어입니다.

문제는 문제가 발생하고 사용자가 비디오를 느리게로드하는 것에 대해 불평하는 경우 그 속도가 궁극적으로 Python의 느린 실행 속도에 기인하는 시나리오는 많지 않다는 것입니다. 그러나 파이썬의 빠른 재 컴파일과 타입 검사없이 새로운 것을 시도 할 수있는 모듈 식 기능은 아마도 엔지니어가 잘못되고있는 것을 매우 빠르게 디버깅 할 수있게 해줄 것입니다. ( "와우. 새로운 인턴은 새로운 SQL 하위 쿼리를 수행하는 루프를 작성했습니다. 모든 결과에 대해. ") 또는 ("Firefox는 이전 캐싱 헤더 형식을 더 이상 사용하지 않으며 새로운 라이브러리를 쉽게 설정하기 위해 Python 라이브러리를 만들었습니다 ")

그런 의미에서, 실행 시간의 관점에서도 모듈 식 언어는 병목 현상이 무엇인지 발견하면 코드를 재구성하는 것이 더 쉬워 져 최상의 방식으로 작동 할 수 있기 때문에 더 빠르다고 생각할 수 있습니다. 따라서 많은 엔지니어들이 성능 저하가 예상했던 위치에 있지 않다고 말할 것입니다 (사실 DID 최적화가 거의 필요하지 않았거나 기대했던 방식으로 작동하지 않았습니다!)


0

예, 아니오 다른 사람들이 먼저 가독성을위한 프로그램을 언급 한 다음 효율성을 높였습니다. 그러나 읽기 쉽고 효율성이 높은 표준 사례가 있습니다. 대부분의 코드는 드물게 실행되므로 어쨌든 코드를 최적화해도 큰 이점을 얻지 못합니다.

Java는 더 작은 함수 호출을 인라인 할 수 있으므로 함수 작성을 피할 이유가 거의 없습니다. 최적화 프로그램은 더 읽기 쉬운 코드로 더 잘 작동하는 경향이 있습니다. 이론적으로 더 빨리 실행해야하는 단축 법을 보여주는 연구가 있습니다. 실제로 더 오래 걸립니다. JIT 컴파일러는 코드가 작고 자주 실행되는 부분을 식별하고 최적화 할 수 있도록 더 잘 작동합니다. 나는 그것을 시도하지는 않았지만 상대적으로 거의 호출되지 않는 하나의 큰 함수는 컴파일되지 않을 것으로 기대합니다.

이것은 Java에는 적용되지 않을 수도 있지만 한 연구에 따르면 다른 메모리 참조 모델이 필요하기 때문에 더 큰 함수가 실제로 느리게 실행되는 것으로 나타났습니다. 하드웨어 및 최적화 프로그램에 따라 다릅니다. 작은 모듈의 경우 메모리 페이지 내에서 작동하는 명령이 사용되었습니다. 함수가 페이지에 맞지 않을 때 필요한 지시 사항보다 빠르고 작습니다.

코드를 최적화하는 동안 가치가있는 경우가 있지만 일반적으로 코드의 위치를 ​​파악하려면 코드를 프로파일 링해야합니다. 나는 종종 내가 예상했던 코드가 아니라는 것을 알았습니다.

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