문제

나는 할 수 없습니다,나의 생활을 위해,정확히 무엇을 기억이 우리의 선생님이 말했다고 바라고 있어요 당신은 아마 알고있다.

이 모듈은"데이터 구조와 알고리즘"그는 우리에게 뭔가의 라인을 따라:

if 문은 가장 비싼 [something].[something]전 등록 [something].

그렇다,나는 끔찍한 메모리고 나는 정말 미안하지만,나는 인터넷 검색에 대한 시간과 아무것도했습니다.어떤 아이디어가?

도움이 되었습니까?

해결책

매우 낮은 수준에서(에서 하드웨어),네, 는 경우s 은 비싸다.이유를 이해하기 위해,당신은 방법을 이해할 파이프라인 작동합니다.

현재 명령을 실행에 저장되는 뭔가가 일반적으로 불렀 시 포인터 (IP)또는 프로그램 카운터 (PC);이러한 용어가 동의어입니다,하지만 서로 다른 사용되는 용어와 다른 아키텍처를 활용할 수 있다.대부분의 지시,PC 에 다음의 명령은 현재의 PC 의 길이가 현재 명령입니다.대부분의 RISC 아키텍처,지침은 모든 일정한 길이,그래서 PC 될 수 있는 증가한 금액입니다.에 대한 CISC 아키텍처와 같은 x86,지침할 수 있는 가변 길이,그래서는 논리를 디코딩하는 명령어는 그 현재 명령은 위치를 찾은 다음 명령입니다.

지시는,그러나,다음 명령을 실행하지 않음 위치한 후 현재 명령입니다.브 gotos-그들은 말로 프로세서 다음 명령입니다.점이 될 수 있습 조건 또는 무조건적으로 위치 고정 또는 계산됩니다.

조건부 대무조건적인 이해하기 쉬운-조건부 지점만 가지고가는 경우 특정 조건을 보유하고(등 여부를 하나의 번호를 같이 다른);는 경우 지점은 촬영하지 않은,제어로 진행한 후 다음 명령어 지점과 같은 정상입니다.을 위해 무조건적인 가지 지점은 항상 촬영됩니다.조건부에 표시 if 문과 제어를 테스트 forwhile 루프가 있습니다.무조건적 지점에서 무한 루프,함수 호출이 반환, breakcontinue 문의 악명 높은 goto 성명,그리고 더 많은(이러한 목록은 지역에 철저).

지 목표는 또 다른 중요한 문제입니다.대부분의 지점이라는 고정된 지점-대상 그들은 특정 위치에는 코드를 컴파일 시에 고정됩니다.이 포함됩 if 문,루프의 모든 종류,정기적인 함수 호출,그리고 더 많은합니다. 계산 지 컴퓨팅 대상의 지점이다.이 포함됩 switch 문이(가끔),에서 반환하는 함수,가상 함수 호출,및 함수 포인터를 호출합니다.

그래서 무엇이든 의미에 대한 성과?프로세서는 지점을 지시 표시 그 자리에 파이프라인,필요한 그 밖으로 계속하는 방법을 채우기 위해 파이프라인.고장여부를 파악하기 위하여 어떤 지시 후에 와 지사 프로그램에서 스트림,필요한 두 가지를 알:(1)경우에는 지점을 찍고(2)의 대상 지점에 있습니다.이 파악라 지점 예측, 며,그것은 어려운 문제입니다.는 경우 프로세서 제대로 추측,프로그램에서 계속됩니다.는 경우가 대신 프로세서 추측 잘못,그것은 단지 몇 시간을 보냈 컴퓨팅 잘못된 것입니다.그것은 지금은 세척하는 그것의 파이프라인을 가진 지침에서 정확한 실행 path.Bottom line:큰 성능했다.

따라서,이유하는 경우 문은 비용으로 인해 지 mispredictions.이것은 단지 가장 낮은 수준에서.을 작성하는 경우 높은 수준의 코드를 걱정할 필요가 없 이러한 세부 사항에 대해서다.당신이해야만 이것에 대해 관심을 작성하는 경우 성능이 매우 중요한 코드에서는 C 또는 어셈블리입니다.는 경우,쓰기,지사-코드 수수하는 코드가 가지는 경우에도 여러 가지 자세한 지침이 필요합니다.거기에 몇 가지 멋진 비트-을 만지작거리 트릭 할 수 있는 계산과 같은 것들 abs(), min(), 고 max() 지 않고 분기.

다른 팁

"비싸다"는 매우 상대적인 용어이며, 특히if"조건의 비용을 계좌로 가져 가야하기 때문에 문의 진술. 이는 몇 가지 짧은 CPU 지침에서부터 원격 데이터베이스로 호출되는 함수의 결과를 테스트하는 것까지 다양합니다.

나는 그것에 대해 걱정하지 않을 것입니다. 임베디드 프로그래밍을하지 않는 한 비용에 대해 걱정해서는 안됩니다.if"전혀. 대부분의 프로그래머에게는 항상 앱의 성능에서 주도 요소가 되십시오.

특히 RISC 아키텍처 마이크로 프로세서에 대한 지점은 가장 비싼 지침 중 일부입니다. 이는 많은 아키텍처에서 컴파일러가 어떤 실행 경로가 가장 가능성이 높은 경로를 예측하고 다음 지침을 실행 파일에 넣을 가능성이 높기 때문에, 지점이 발생하면 이미 CPU 캐시에있을 것입니다. 지점이 다른 방향으로 가면 메인 메모리로 돌아가 새로운 지침을 가져와야합니다. 상당히 비쌉니다. 많은 RISC 아키텍처에서 모든 지침은 분기 (종종 2주기)를 제외한 한주기입니다. 우리는 여기서 큰 비용에 대해 이야기하고 있지 않으므로 걱정하지 마십시오. 또한, 컴파일러는 시간의 99%보다 더 잘 최적화됩니다 :) Epic Architecture (Itanium)에 대한 정말 멋진 것 중 하나는 분기의 양쪽에서 캐시 (및 처리를 시작) 지침을 시작한다는 것입니다. 그런 다음 지점의 결과가 알려진 후에 필요하지 않은 세트를 버립니다. 이로 인해 예측되지 않은 경로를 따라 분기되는 경우 일반적인 아키텍처의 추가 메모리 액세스가 절약됩니다.

기사를 확인하십시오 지점 제거를 통한 더 나은 성능 셀 성능에. 또 다른 재미는입니다 이 게시물은 Branchless 선택에 관한 것입니다 실시간 충돌 감지 블로그.

이 질문에 대한 응답으로 이미 게시 된 훌륭한 답변 외에도 "If"진술이 비싼 저수준 작업으로 간주되지만 더 높은 수준의 환경에서 분기없는 프로그래밍 기술을 활용하려고 노력하고 있음을 상기시키고 싶습니다. 스크립팅 언어 또는 비즈니스 로직 계층 (언어에 관계없이)과 같은 것은 엄청나게 부적절 할 수 있습니다.

대부분의 시간, 프로그램은 명확성을 위해 가장 먼저 작성하고 두 번째로 성능을 위해 최적화해야합니다. 성능이 가장 중요한 수많은 문제 도메인이 있지만 간단한 사실은 대부분의 개발자가 렌더링 엔진의 핵심 또는 몇 주 동안 실행되는 고성능 유체 역학 시뮬레이션의 깊은 곳에 사용하기 위해 모듈을 작성하지 않는다는 것입니다. 최우선 과제가 귀하의 솔루션이 "작업"하는 것입니다. 마지막으로 마음의 마지막 것은 코드에서 조건부 명세서의 오버 헤드를 절약 할 수 있는지 여부입니다.

가능한 최저 수준에서 if (특별한 모든 앱 특정 전제 조건을 계산 한 후 if):

  • 일부 테스트 지침
  • 테스트가 성공하면 코드의 어느 장소로 이동하면 그렇지 않으면 앞으로 진행합니다.

그와 관련된 비용 :

  • 낮은 레벨 비교 - 보통 1 CPU 작동, 매우 저렴
  • 잠재적 인 점프 - 비용이 많이들 수 있습니다

RESON 점프가 비싼 이유 :

  • CPU에 의해 캐시되지 않는 것으로 밝혀지면 메모리에 사는 곳에 사는 arbirary 코드로 점프 할 수 있습니다. 우리는 문제가 있습니다. 우리는 메인 메모리에 액세스해야하기 때문에 더 느리게됩니다.
  • 현대 CPU는 분기 전임을합니다. 그들은 파이프 라인에서 성공할 것인지 아닌지를 추측하려고 노력하고 파이프 라인에서 코드를 실행하므로 속도를 높이십시오. 예측이 실패하면 파이프 라인에 의해 미리 수행 된 모든 계산은 무효화되어야합니다. 그것은 또한 비싼 작업입니다

요약하려면 :

  • expesive가 될 수 있다면, 당신이 실제로, 실제로, 성능에 관심을 갖는다면.
  • 당신은 그것에 관심을 가져야합니다 경우에만 당신은 실시간 Raytracer 또는 생물학적 시뮬레이션 또는 이와 유사한 것을 쓰고 있습니다. 대부분의 현실 세계에서 그것을 돌볼 이유가 없습니다.

if 그 자체로 ~ 아니다 느린. 속도는 항상 내 인생에서 당신이 IF 진술의 "오버 헤드"를 느끼지 못했다고 생각합니다. 고성능 코드를 만들려면 어쨌든 가지를 피하고 싶습니다. 무엇을 만드는 것 if 느리게 프로세서가 이후에서 코드를 예압한다는 것입니다. if 휴리스틱과 무엇을 기반으로합니다. 또한 파이프 라인이 코드를 실행하는 것을 막을 것입니다. if 기계 코드의 분기 명령어는 프로세서가 아직 어떤 경로를 촬영할 것인지 알지 못하므로 (파이프 라인 프로세서에서는 여러 명령어가 인터리브 및 실행됩니다). 실행 된 코드는 반대로 실행해야 할 수 있습니다 (다른 지점이 채취 한 경우. branch misprediction), 또는 noop이 장소에서 이런 일이 일어나지 않도록 채워집니다.

만약에 if 그렇다면 악입니다 switch 도 악하고 &&, || 도. 그것에 대해 걱정하지 마십시오.

어쩌면 분기가 CPU 명령을 프리 페치를 죽일 수 있을까요?

최신 프로세서에는 긴 실행 파이프 라인이있어 여러 단계에서 동시에 몇 가지 지침이 실행됩니다. 다음 명령이 실행되기 시작할 때 항상 한 가지 지시의 결과를 알지 못할 수도 있습니다. 그들이 조건부 점프에 들어가면 (if) 때때로 명령 포인터가 어떤 방법으로 가야하는지 알기 전에 파이프 라인이 비어있을 때까지 기다려야합니다.

나는 그것을 긴화물 열차라고 생각합니다. 그것은 많은화물을 직선으로 빨리 운반 할 수 있지만 코너가 심하게 나쁘게 운반 할 수 있습니다.

Pentium 4 (Prescott)는 31 단계의 유명한 파이프 라인을 가졌습니다.

위키 백과

내가 이것을 언급 할 수 있다고 상상할 수있는 유일한 것은 if 진술은 일반적으로 분기를 초래할 수 있습니다. 프로세서 아키텍처의 세부 사항에 따라 분기는 파이프 라인 스톨 또는 기타 최적의 상황이 아닌 다른 상황을 유발할 수 있습니다.

그러나 이것은 매우 상황에 따라 다릅니다. 대부분의 현대 프로세서에는 분기의 부정적인 영향을 최소화하려는 분기 예측 기능이 있습니다. 또 다른 예는 ARM 아키텍처 (및 아마도 다른 사람들)가 조건부 논리를 처리 할 수있는 방법입니다. ARM에는 지시 수준 조건부 실행이 있으므로 간단한 조건부 논리는 분기가 없습니다. 지침은 조건이 충족되지 않으면 단순히 노프로 실행됩니다.

말한다 -이 물건에 대해 걱정하기 전에 논리를 올바르게 얻으십시오. 잘못된 코드는 최적화되지 않습니다.

많은 사람들이 지적했듯이, 현대 컴퓨터에서는 조건부 분기가 매우 느릴 수 있습니다.

즉, 성명서에 살지 않는 조건부 지점이 많이 있습니다. 컴파일러가 무엇을 할 것인지 항상 알 수는 없으며 기본 진술이 얼마나 오래 걸릴지 걱정하는 것은 사실상 항상 잘못된 것입니다. 할 것. (컴파일러가 무엇을 안정적으로 생성 할 것인지 알 수 있다면 최적화 된 컴파일러가 없을 수 있습니다.)

CPU는 깊이 파이프 라인되어 있습니다. 모든 분기 명령어 (/for/while/switch/etc)는 CPU가 다음에로드하고 실행할 지침을 실제로 알지 못한다는 것을 의미합니다.

CPU는 무엇을 해야하는지 기다리는 동안 마구간을 중단하거나 CPU가 추측합니다. 구형 CPU의 경우 또는 추측이 잘못된 경우 파이프 라인 마구간을 겪고 올바른 지침을로드해야합니다. CPU에 따라 이것은 10-20 지침의 스톨만큼 높을 수 있습니다.

현대 CPU는 좋은 지점 예측을 수행하고 동시에 여러 경로를 실행하고 실제 경로를 유지함으로써이를 피하려고 노력합니다. 이것은 많은 도움이되지만 지금까지 갈 수 있습니다.

수업에서 행운을 빕니다.

또한 실생활에서 이것에 대해 걱정해야한다면 아마도 OS 디자인, 실시간 그래픽, 과학 컴퓨팅 또는 유사한 CPU에 대한 작업을 수행 할 수 있습니다. 걱정하기 전에 프로필.

또한 루프 내부는 다음과 같습니다 ~ 아니다 반드시 매우 비쌉니다.

현대 CPU는 IF 진술을 처음 방문했을 때 "IF-BODY"를 취해야한다고 가정합니다 (또는 다른 방법으로도 루프 바디를 여러 번 복용해야한다고 가정합니다) (*). 두 번째와 추가 방문은 IT (CPU)를 조사 할 수 있습니다. 지점 기록 테이블, 그리고 조건이 어떻게 마지막 시간인지보십시오 (사실입니까? 거짓입니까?). 마지막으로 거짓 인 경우 투기 실행은 IF의 "else"또는 루프를 넘어 진행됩니다.

(*) 규칙은 실제로 "앞쪽 지점을 가져 가지 않고 뒤로 지점을 가져옵니다". if 진술에는 있습니다 앞으로] 점프 (포인트까지 IF-BODY 후) 조건이 False로 평가되면 (기억하십시오 : CPU는 어쨌든 분기/점프를 취하지 않는다고 가정합니다), 루프에는 루프 후 위치에 대한 전방 분기가있을 수 있습니다 (가져 가지 않음). repetetion에 분기 (취해야 할).

이것은 또한 가상 함수 또는 함수 포인터 호출에 대한 호출이 많은 사람들이 가정 하듯이 더 나쁘지 않은 이유 중 하나입니다.http://phresnel.org/blog/)

프로그램을 가장 비효율적이지 않은 가장 명확하고 단순하며 깨끗한 방법으로 작성하십시오. 그것은 가장 비싼 자원을 가장 잘 활용합니다. 프로그램을 작성하거나 나중에 디버깅해야합니다 (이해가 필요). 성능이 충분하지 않으면 측정하다 병목 현상이있는 곳에,이를 완화하는 방법을보십시오. 매우 드문 경우에만 개인 (출처) 지침에 대해 걱정해야합니다. 성능은 첫 번째 줄에서 올바른 알고리즘과 데이터 구조를 선택하여 신중하게 프로그래밍하여 빠른 기계를 얻는 것입니다. 좋은 컴파일러를 사용하면 최신 컴파일러를 재구성하는 코드의 종류를 볼 때 놀랄 것입니다. 성능을위한 구조 조정 코드는 일종의 최후의 수단 측정이며, 코드는 더욱 복잡 해져서 수정하기가 어렵 기 때문에 더 비쌉니다.

나는 내 친구와 한 번이 주장을했다. 그는 매우 순진한 원형 알고리즘을 사용하고 있었지만 내 IF를 사용했기 때문에 내 것보다 더 빠르다고 주장했습니다 (원의 1/8 만 계산하는 종류). 결국, IF 문은 SQRT로 대체되었고 어떻게 든 더 빠릅니다. 아마도 FPU에 SQRT가 내장되어 있기 때문에?

일부 CPU (x86과 같은)는 이러한 분기 예측 대기 시간을 피하기 위해 분기 예측에 프로그래밍 레벨을 제공합니다.

일부 컴파일러는 (GCC와 같은) 노출을 노출시킵니다.

나타내다 Linux 커널의 가능성 ()/가능성이 낮은 () 매크로 - 어떻게 작동합니까? 그들의 이익은 무엇입니까?.

ALU 사용 측면에서 가장 비싼? CPU 레지스터를 사용하여 비교할 값을 저장하고 IF 문을 실행할 때마다 값을 가져오고 비교하는 데 시간이 걸립니다.

따라서 최적화는 루프가 실행되기 전에 하나의 비교를 수행하고 결과를 변수로 저장하는 것입니다.

누락 된 단어를 해석하려고합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top