오늘날 프로그래머들은 무엇을 "미세 최적화"합니까? [닫은]


14

우리가 친구들을 위해 플로피에 쉐어웨어를 복사 할 때 "좋은 일"로 돌아가서, 우리는 또한 약간의 어셈블리를 사용했습니다. 한 번의 적은 명령으로 표현할 수있는 방법을 찾을 때까지 조립 라인을 응시하는 "미세 최적화"라는 일반적인 관행이있었습니다. 수학적으로 불가능하다는 말도있었습니다 . " 언제나 하나의 명령을 더 이상 제거 할 수 있습니다. "작은 상수 요소로 런타임 성능을 변경하는 것이 오늘날 (대부분) 프로그래밍의 주요 문제가 아니라는 점을 감안할 때 프로그래머는 이러한 마이크로 다른 곳에서 최적화 노력?

다시 말해, 모범 사례를 더 이상 가치가없는 극단적 인 상태로 만들 수 있습니까? 대신 시간을 낭비하고 있습니까?

예를 들어, 프로그래머 는 한 곳에서만 호출되는 개인 메소드를 일반화 하는 데 시간을 낭비 합니까? 테스트 사례 데이터를 줄이는 데 시간이 낭비됩니까? 프로그래머 (여전히)는 코드 줄을 줄이는 데 지나치게 관심이 있습니까?

내가 찾고있는 것에 대한 두 가지 훌륭한 예가 있습니다. (2) 사소하고 열악한 코드 중복 제거.


이 질문은 " 무엇을 최적화합니까? " 라는 질문과 다릅니다. 다른 프로그래머가 "마이크로"최적화라는 오명을 사용하여 시간을 생산적으로 사용하지 않기 때문에 다른 프로그래머가 최대화 할 것으로 보이는 것입니다.



@ Macneil, 다른 프로그래머가 마이크로 최적화하는 것이 무엇인지 모르겠지만 그럴 시간이 없습니다. 저의 동료들도 바쁩니다 (2 센트 만).
Job

@Job : 아무 이유없이 코드를 바꾸면서 시간을 낭비하는 사람을 본 적이 없습니까? 운이 좋다고 생각하십시오. 변수 이름과 부 코드 중복이라는 두 가지 훌륭한 예가 아래에 있습니다.
Macneil

1
현재 말했듯이 질문은 개선입니다. 마감 투표를 제거 할 수는 없지만 며칠 후에 만료됩니다. 실제로, 그 질문은 꽤 좋은 답변을 모으고 있습니다.
Robert Harvey

1
BTW, 모든 모범 사례는 더 이상 가치를 창출하지 않을 정도로 극단적으로 이루어질 수 있습니다.
Robert Harvey

답변:


22

코드 포맷

Don't     get    me   wrong             ,
code      should be   consistent        & 
readable                                , 
but       some   take it         too far.

예, 좋은 오래된 변수 유형과 변수 이름에는 일련의 변수 선언에 자체 열이 필요합니다. 오! =이니셜 라이저에 대한 및 네 번째에 대한 추가 행을 잊어 버렸습니다 !
Macneil

[Darn, upvote,하지만 내 일일 한도에 도달 ...]
Macneil

3
우리 교수들은 이런 식으로 과제물을 작성하기 위해 코드를 포맷하도록 강요했습니다. 이 습관을 없애기 위해 몇 년이 걸렸습니다.
Oliver Weiler

이런. 다른 답변에서 나는 웃고 있었지만 이것은 정말로 아프다 :-(
Steve314

2
+1 한 번은 열 형식 코드를 망쳐 서 개발자가 코드를 수정하지 않은 라이브러리에서 작업 한 적이 있습니다.
Dean Harding

20

나는 하루에 많은 어셈블러를 쓰곤했었다. 컴파일러가 더 나아 졌을뿐만 아니라, 대부분의 하드웨어에는 이제 비 순차적 코드 실행에 전념하는 많은 논리가 있습니다. 실제 마이크로 이슈는 스케줄링이며, 대부분의 컴퓨터 명령어는 결과를 생성하기 위해 여러 머신 클럭을 필요로합니다. 캐시를 놓치는 메모리로드에는 수백이 걸릴 수 있습니다! 따라서 결과를 기다리지 않고 다른 지침을 사용하여 유용한 것을 수행하도록 계획했습니다. 그리고 현대 기계는 클럭주기마다 몇 가지 명령을 내릴 수 있습니다. 우리가 고장난 실행 HW를 시작한 후, 핸드 코딩으로 뛰어난 성능을 얻으려고 노력하는 것이 머그컵 게임이라는 것을 알았습니다. 먼저 비 순차적 HW는 신중하게 만들어진 순서대로 명령을 실행하지 않습니다. 새롭고 멋진 HW 아키텍처는 컴파일러가 일반적으로 성능의 몇 퍼센트 내에있을 정도로 불충분 한 소프트웨어 스케줄링의 형벌을 줄였습니다. 또한 컴파일러가 언 롤링, 맨 아래 로딩, 소프트웨어 파이프 라이닝 등과 같은 잘 알려져 있지만 복잡성을 생성하는 트릭을 구현하고 있음을 알았습니다. 결론은 실제로 열심히 노력해야하며 이러한 트릭 중 일부를 건너 뛰면 컴파일러가 당신을 이길 수 있다는 것입니다. 그것들을 모두 사용하고 필요한 어셈블러 명령어 수를 몇 배 늘려야합니다!

아마도 가장 중요한 성능 문제는 아마도 명령 문제 비율이 아니라 데이터를 CPU로 가져 오는 것입니다. 위에서 언급했듯이 메모리 대기 시간은 이제 수백 사이클이며 CPU는 클럭 기간마다 여러 개의 명령을 실행할 수 있으므로 프로그램 및 특히 데이터 구조가 캐시 적중률이 지나치게 높도록 명령에서 미세 조정되도록 설계되지 않는 한 레벨에는 보상이 없습니다. 군대 유형이 아마추어가 전술을 이야기하는 것처럼, 전문가는 물류를 이야기합니다. 성능 프로그래밍은 이제 90 % 이상의 물류 (이동 데이터)입니다. 최신 메모리 관리에는 일반적으로 여러 수준의 캐시가 있으며 가상 메모리 페이지는 TLB라는 하드웨어 단위로 처리되므로 수량화하기가 어렵습니다. 또한 실제 데이터 전송이 바이트 단위가 아니기 때문에 주소의 하위 수준 정렬이 중요해집니다. 또는 64 비트 긴 길이이지만 캐시 라인 단위로 제공됩니다. 그런 다음 대부분의 최신 컴퓨터에는 가까운 시일 내에 어떤 캐시 라인 미스를 예측하고 자동 프리 페치를 발행하여 캐시로 가져 오는 하드웨어가 있습니다. 따라서 현실은 현대 CPU의 경우 성능 모델이 거의 이해할 수 없을 정도로 복잡하다는 것입니다. 세부적인 하드웨어 시뮬레이터조차도 칩의 정확한 로직과 절대 일치 할 수 없으므로 더 이상 정확한 튜닝이 불가능합니다.

수작업 코딩을위한 장소가 여전히 있습니다. 더 중요한 선형 대수 연산 (매트릭스 곱하기와 같은)과 같은 수학 라이브러리는 일반적으로 하드웨어 공급 업체 (예 : Intel 또는 AMD 또는 IBM)에서 일하는 전문가에 의해 여전히 수작업으로 코딩됩니다. 메가 컴퓨터 회사 당 최고 수준의 어셈블러 프로그래머가 필요합니다.


1
작업은 내부자 지식 및 공급 업체별 도구 (컴파일러 및 프로파일 러)에 점점 더 의존하기 때문에 CPU 공급 업체 외부에서 일하는 사람에게는 핸드 코딩이 점점 어려워지고 있습니다. spiral.net은 CPU 최적화를 모델링하고 최적의 솔루션 검색을 자동화하려고합니다.
rwong

많은 컴퓨터 언어는 프로그래머가 결과를로 표현할 계산에 배정도를 사용하는 것을 고통스럽게함으로써 무의미하게 미세 최적화하도록 강요합니다 float. 어떤 이유로 나는 설득력이 없다, 많은 사람들이 이것이 좋은 것이라고 생각하는 것을 본다.
supercat

10

변수 나 분석법에 대한 적절한 이름을 선택하는 동안 시간을 ​​낭비 (폐기물?)하는 데 시간이 많이 걸리므로 정확하게 설명 할뿐만 아니라 언어 스타일도 좋습니다.

전체 작품 (프로그램)을 동일한 언어 스타일로 넣으려고하면 조금 더 나아갑니다. 때때로 내 의견이 바뀌고 책을 수정합니다. :)

시간이 오래 걸리지 않습니다. 오히려 드물다. 그러나 저는 프로그램에서 좋은 문법을 유지하고 싶습니다.


3
명명이 어렵다. 따라서 훨씬 더 나은 이름을 생각할 때 이름을 리팩터링해야합니다. 이것은 마음의 노력을 포착하고 "왜"도 희망적으로 결정한다는 것을 명심하십시오.

1
이것은 매우 좌뇌 된 것입니다 (뇌의 왼쪽은 언어 처리를 담당합니다). 올바른 두뇌를 ​​가진 프로그래머로서 나는 의미론에 대해 걱정하는 데 훨씬 적은 시간을 소비하고 모든 조각이 어떻게 결합되는지에 대해 더 많은 시간을 소비하는 경향이 있습니다.
Jason Baker

7
변수 및 메서드 명명은 유지 관리의 중요한 부분입니다. 하나는 해야 지금부터 그 오년 있도록 코드를 유지하는 사람은 그것으로 쉽게 시간을 가지고, 이름에 대한 시간 생각을 보낸다.
GrandmasterB

@grandmaster : 더 동의 할 수 없습니다.
Robert Harvey

4
@ right-brainers : lef-tbrainers를 위해 코드를 작성해주세요. 그래서 코드도 읽을 수 있습니다
Juan Mendes

10

시간 복잡성. 프로그램에서 실제로 발생할 수있는 것보다 훨씬 큰 규모로 최악의 경우 성능을 최적화하는 데 너무 많은 시간을 소비합니다.

나는 다른 디자인 결정이 현실적으로 일어나지 못하게 할 때조차도 '그러나 그 큰 뼈를 자랄 있습니다.'

그러나 내 방어에서는 비현실적이 현실이되어야한다. 최적화는 더 이상 '마이크로'가 아니다. 나는 불가능하다고 말하지 않았지만 비현실적 이었다.

물론 요구 사항이 우선합니다.


1
이 때문에 침몰 한 회사에서 근무했습니다.
Henry

2
@ 헨리-약속 해, 난 아니 었어 :)
Tim Post

1
@Henry : 당신은 그들이 가능성이 결코 일어나지 않을 것입니다 것들에 대한 최적화 시간을 낭비하거나 의미 하지 않았다 그들이 때까지 ... 가능성이 발생하지 "않을 것"이라고 것들에 대해 생각 했던 일이하고 너무 늦었다?
Dean Harding

2
@ 헨리 (Henry) : 회사가 확장 성이 뛰어난 제품을 가지고 있고 여전히 침몰 한 경우, 이는 개발이 아니라 판매량과 마케팅의 결함 (대량 고객을 대상으로하지 않고 적절하게 가격을 책정하지 않음)입니다.
rwong

1
이 회사는 1 명의 사용자가없는 수백만 명의 사용자를위한 시스템을 설계하는 데 너무 많은 시간을 보냈습니다. 마케팅 결함이었을 것입니다. 그래, 마케팅을 비난하자 그 사람들은 바보 야.
Henry

8

Java 예외 처리기를 사용하여 몇 주 동안 시간을 ​​낭비했다고 생각합니다.

이것은 일년에 두세 번 실패하는 코드에 많은 작업입니다. 이것이 경고 또는 정보 여야합니까? 오류 또는 치명적? 5 분 안에 프로세스가 다시 생성되는 것이 실제로 치명적입니까? 모든 것이 여전히 기본 상태 인 경우 실제로 경고입니까?

IO 오류의 본질에 대한 많은 배꼽 응시와 토론. 네트워크를 통해 파일을 읽을 수 없으면 파일 오류입니까 아니면 네트워크 오류입니까? 등등.

어느 시점에서 나는 모든 concat 문자열을 교체 String.format하여 연간 파일 오류로 인해 힙에 추가 객체가 발생하지 않습니다. 그것은 낭비였다.


3
이것은 중요한 일입니다. 실패 가격 = 매일 WTF에 표시되는 오류 메시지.
Steve314

7

LOC에 너무 관심이 있다고 생각합니다. 많은 LOC 자체가 아니라 많은 수의 문과 더 많은 수의 중복 된 문입니다. 코드를 복제하는 데 알레르기가 있습니다. 일반적으로 리팩토링을 좋아하지만, 내가하는 것의 약 50 %가 코드를 훨씬 더 멋지게 만들지 않는다고 생각합니다.


4
"코드 복제에 알레르기가 있습니다"+1 여기 내 답변을 참조하십시오 : programmers.stackexchange.com/questions/14610/…
Macneil

생각하기-Knuth가 goto에 대해 한 점과 관련이있는 루프 와이 문제가 있으며 때로는 구조적 코드를 작성하기 위해 사이클 또는 두 개 또는 중복 코드를 교환해야합니다. 나는 것이다 매우 드문 경우에 고토 (가장 일반적인 = 생성 된 코드)를 사용하지만,이 질환의 나의 변화는 시간이 걱정하고 루프가 끝없이 사소한 비 효율성을 제거 아직 코드를 읽을 수를 유지하려고 만지작을 낭비하고있다.
Steve314

5

전체 줄을 문자열로 읽는 대신 한 줄씩 파일을 읽고 한 번에 문자열을 처리하십시오.

물론, 실행 속도에는 차이가 있지만 여분의 코드 줄에는 가치가 거의 없습니다. 코드 유지 관리가 훨씬 덜하고 코드 크기가 증가합니다.

예, 파일 크기가 3GB이지만 대부분의 파일이 크지 않은 경우 (적어도 ;-) 파일이 아닌 경우) 이것은 의미가 없습니다.


3
3GB 이상이더라도 64 비트 시스템은 가상 메모리로 처리 할 수 ​​있습니다. 메모리 매핑 파일을 사용하면 필요할 때까지 파일의 일부를 읽지 않습니다. 정상적인 경우에도 미세 최적화입니다.
Steve314

3

어셈블리 언어를 작성할 때 바이트와 사이클을 nitpick하는 것이 이치에 맞았지만 오래 전부터 컴파일러는 먼 길을 왔습니다. 지금은 수동으로 수동 최적화를 시도하지 않습니다.

마찬가지로 C로 쓰는 것으로 전환했을 때 C 컴파일러보다 더 나은 작업을 수행하는 것이 매우 쉽지만 매년 Borland 또는 Microsoft 또는 누군가가 이전의 새로운 것을 개선 할 것입니다. 컴파일러가 방출하는 실제 어셈블리 코드에주의를 기울이기 시작했고, 훌륭하고 단단한 코드를 작성하지 않으면 루프를 풀고 루프 외부로 변수를 이동하는 등의 작업을 수행했습니다.

이제는 Perl, Python 및 Ruby와 같은 훨씬 더 높은 언어로 글을 쓰고 있습니다. 루프 언 롤링이 의미가있는 경우 루프 언 롤링, 루프 외부에서 정적 변수 이동 등과 같은 컴파일러 트릭을 미리 사용하지만 CPU가 훨씬 빠르기 때문에 거의 걱정하지 않습니다. 응용 프로그램이 예기치 않게 드래그하는 것처럼 보이는 경우 프로파일 러를 사용하여 찾을 수있는 항목을 확인한 다음 개선 할 수있는 경우 다양한 방법으로 벤치마킹을 시작하여 더 빠른 작업을 수행 할 수있는 방법을 확인한 다음 방법을 확인합니다. 스케일 업.

일반적으로 나는 수년간의 경험을 바탕으로 코드를 작성하는 방법을 현명하게하려고합니다.


안녕 그렉, 답변 주셔서 감사하지만 프로그래머가 런타임 성능을 최적화하지 않고 시간 을 낭비하는 일을 찾고 있습니다. 위의 두 가지 훌륭한 예가 있습니다 : 변수 이름과 작은 코드 복제 제거.
Macneil

3

마이크로 최적화 : 병렬화 가능하거나 새로운 하드웨어로 간단하게 개선 할 수있는 것의 단일 스레드 성능 향상.

10 년 전부터 컴퓨터의 속도가 느리면 프로그래머가 시간을 낭비하지 않고 새롭고 빠른 컴퓨터를 구입하는 것이 더 저렴한 솔루션 일 것입니다. 하지만 최적화에 중점을 두는 것은 오늘날 얻을 수있는 8 개의 코어를 사용하는 방법을 찾거나 추가 쓰레기 비용과 같이 미세한 것에 대해 고민하는 대신 몇 년 안에 얻을 수있는 64 개의 코어를 사용하는 방법을 찾는 것입니다 수집.


2

런타임 성능 측면에서 마이크로 최적화는 오늘날조차도 닫힌 문제가 아닙니다 (흔하지는 않지만). 때로는 요청마다 추가 객체를 할당하거나 추가 함수 호출을 추가하는 오버 헤드가 무시할 수 있다고 사람들에게 설명해야합니다.

그 외에도 프로그래머도 단순성을 위해 마이크로 최적화를합니다 (자신 포함). 나는 단순성과 단순성의 차이점을 설명 할 필요가없는 곳에서 아직 일하지 않았다.


프로그래머가 왜 그런가? 다른가? 차이점은 무엇입니까?
Dan Rosenstark

@Yar-왜 프로그래머가 다른 것과 다른가?
Jason Baker

왜 것 programmers.= programmers.stackexchange.com당신은이 두 개념의 차이를 설명 했어 당신이 작업 한 것을 모든 장소에서 어떤 다를 수? 차이점을 설명하십시오.
Dan Rosenstark

@Yar-잘 모르겠습니다. 실제로 programs.se의 요점은 프로그래머가 지식을 모으는 데 도움이되므로 사람들이 적어도 내 대답에 약간의 깨달음을 얻지 않기를 바랍니다.
Jason Baker

2
그렇다면 b / t 단순성과 단순성의 차이점은 무엇입니까?
Dan Rosenstark

2

나는 실제로 필요한 원칙을 최적화하지 않는 한 최선을 다한다. 그리고 저는 프로필 우선 원칙을 따르고 있습니다. 그리고 원칙적으로 필요한 차이를 만들 수있는 무언가 만 최적화합니다.

그게 원칙입니다. 그러나 원칙은 거짓말 쟁이입니다.

내부 루프에서 많이 사용될 것으로 생각되는 자주 사용되는 라이브러리의 함수를 관리하는 습관이 있습니다. 그런 다음 다른 기능에서 무언가를 발견하면 자주 사용되지 않습니다 ...

아, 그리고 "필자가 쓰고 있습니다-물론 중요한 라이브러리입니다"라는 논리가 있습니다.

아-그리고 BTW. 나는 아직 최적화를 안내하기 위해 프로파일 러를 사용한 적이 없다. 상업용 광고에 액세스 할 수 없으며 gprof를 파악하려는 동기를 구축하지 마십시오.

기본적으로, 나는 위선자입니다. 이 원칙은 다른 사람들에게 적용되지만 "누가 왜 그렇게 느리고 삐걱 거리는 방식으로 글을 쓰셨습니까?" 그래서 나는 그들 자신을 제대로 적용 할 수 없습니다.

그래도 내가 여기서 만드는 것만 큼 나쁘지는 않습니다. 그리고 나는 자기기만에 완전히 면역입니다. 그래서 당신은 내가 그것에 대해 옳다는 것을 압니다!

편집하다

나는 추가해야한다 – 나의 주요 어리석은 끊기는 전화 오버 헤드이다. 물론 모든 곳에서가 아니라 내가 생각할 수있는 많은 루프에서 내부 루프 사례 (문제에 대한 객관적인 증거가없는 곳). 가상 메소드 호출을 두 번 이상 피하는 것을 피하기 위해 불쾌한 오프셋 코드를 작성했습니다. 옵티마이 저가 잘 처리하도록 설계된 코딩 스타일이 아니기 때문에 결과가 더 느려질 수도 있습니다.하지만 영리합니다 .


+1 아, 그렇습니다! 이 클래스는 내 응용 프로그램의 매우 구체적이고 기발한 명령 줄 인수를 구문 분석하지만 Javadoc을 사용하면 형식을 지정하고 완전히 문서화 할 수 있습니다. [나중에 upvote 필요, 내 일일 한도에 도달합니다.]
Macneil

@ Macneil-Doxygen입니다. 알려 드리겠습니다. 모든 옵션을 사용하면 스위치를 찾을 수 있으므로 모든 작은 함수가 12 가지의 예쁜 GraphViz 그래프로 완성 된 세부적인 "문서화"됩니다. 내 코드가 얼마나 중요한지 모든 사람이 감사하게 생각할 수 있습니다. 출력물은 아주 큰 사무실 블록을 벽지로 만들 수 있습니다.
Steve314

1

컴퓨터가 클럭 시간을 마이크로 초, 킬로바이트로 측정 한 메모리 및 원시 컴파일러로 사용하던 시절에는 마이크로 최적화가 의미가있었습니다.

현재 세대 컴퓨터의 속도와 크기 및 현재 세대 컴파일러의 품질은 마이크로 최적화가 일반적으로 시간 낭비라는 것을 의미합니다. 예외는 당신이 때 경향이 절대적으로해야 할 몇 가지 계산 집약적 인 코드에서 최대 성능을 얻을 ... 또는 당신은 매우 제한된 자원을 가진 임베디드 시스템을 위해 쓰고있다.

그러나 나는 프로그래머가 런타임 성능을 최적화하지 않고 시간을 낭비하기 위해 무엇을하는지 찾고 있습니다.

트위터와 페이스 북이 떠오른다 :-)


안녕 스티븐, 그것은 미세 최적화에 대한 훌륭한 논평이지만 현대의 동등한 것들을 보십니까? [페이스 북과 트위터는 너무나 잘 전달 될 수있는 "모범 사례"가 아닙니다.]
Macneil

여전히 이해가됩니다. 클럭 시간은 수십 배 더 작을 수 있지만 코드는 수십 배 더 큽니다.
hplbsh

@Stuart-그것은 마이크로 스케일링하기 위해 더 많은 코드가 있다는 것을 의미합니다 ... 단순히 확장되지 않습니다.
Stephen C
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.