문제

boolean a = false, b = true;
if ( a && b ) { ... };

대부분의 언어에서는 b 평가를 받지 못하기 때문에 a 거짓이므로 a && b 사실일 수 없습니다.내 질문은 아키텍처 측면에서 단락이 더 느리지 않을까요?파이프라인에서는 b를 평가해야 하는지 여부를 결정하기 위해 a의 결과를 기다리는 동안 그냥 멈추나요?대신 중첩된 if를 수행하는 것이 더 낫습니까?그게 도움이 되나요?

또한 일반적으로 단락 평가가 무엇인지 아는 사람이 있습니까?이 질문은 내 프로그래밍 친구가 단락 평가에 대해 들어본 적이 없고 그것이 일반적이지 않고 많은 언어에서 발견되지 않으며 파이프라인에서 비효율적이라고 말한 후에 발생했습니다.마지막은 잘 모르겠어서 질문드립니다!

좋아, 내 친구가 어디에서 왔는지 설명하기 위해 다른 예를 생각합니다.그는 다음과 같은 진술을 병렬로 평가한 이후 다음과 같이 믿습니다.

(a) if ( ( a != null ) && ( a.equals(b) ) ) { ... }

시스템이 중단될 수 있습니다. 단락이 없는(따라서 위와 같은 명령문을 허용하지 않는) 아키텍처는 다음과 같은 명령문을 처리하는 데 더 빠릅니다.

(b) if ( ( a == 4 ) && ( b == 5 ) )

왜냐하면 (a)를 병렬로 수행할 수 없다면 (b)도 병렬로 수행할 수 없기 때문입니다.이 경우 단락을 허용하는 언어는 그렇지 않은 언어보다 느립니다.

그것이 사실인지 아닌지는 모르겠습니다.

감사해요

도움이 되었습니까?

해결책

단락 부울 표현식은 일부 중첩된 if 세트와 정확히 동일하므로 그만큼 효율적입니다.

b에 부작용이 없는 경우에도 a와 병렬로 실행될 수 있습니다(파이프라인을 포함하여 "병렬" 값에 대해).

b에 분기 예측이 실패할 때 CPU 아키텍처가 취소할 수 없는 부작용이 있는 경우 그렇습니다. 양측이 항상 평가된 경우 발생하지 않는 지연이 필요할 수 있습니다.따라서 단락 연산자가 코드에서 성능 병목 현상을 일으키는 것을 발견한 경우 살펴봐야 하지만 그렇지 않은 경우에는 걱정할 가치가 없습니다.

그러나 불필요한 작업을 줄이는 만큼 제어 흐름에는 단락이 사용됩니다.Perl 관용구와 같이 내가 사용한 언어에서는 일반적입니다.

open($filename) or die("couldn't open file");

쉘 관용어:

do_something || echo "that failed"

또는 C/C++/Java/etc 관용구:

if ((obj != 0) && (obj->ready)) { do_something; } // not -> in Java of course.

이 모든 경우에 단락이 필요하므로 LHS가 이를 지시하는 경우에만 RHS가 평가됩니다.이러한 경우 잘못된 대체 코드와 성능을 비교할 이유가 없습니다!

다른 팁

단락 평가는 if 문과 동일한 방식으로 어셈블리 언어의 분기로 변환됩니다(분기는 기본적으로 goto입니다). 이는 if 문보다 느리지 않음을 의미합니다.

분기는 일반적으로 파이프라인을 지연시키지 않지만 프로세서는 분기가 수행되었는지 여부를 추측하고 프로세서가 잘못된 경우 파이프라인에서 잘못된 추측을 한 이후 발생한 모든 것을 플러시해야 합니다.

단락 평가는 가장 일반적인 이름이기도 하며 대부분의 언어에서 어떤 형태로든 발견됩니다.

나는 솔직히 그것에 대해 걱정하지 않을 것입니다.부울 테스트는 정말 빠르다.단락은 두 번째 표현식에 부작용이 있을 때만 흥미롭고 유용합니다.

if ( ConfirmAction() && DestroyAllData() )
   Reboot();

...또는 첫 번째 테스트에 따라 다릅니다.

if ( myDodgyVar != null && myDodgyVar.IsActive() )
   DoSomethingWith(myDodgyVar);

단락을 지원하는 언어:

Ada, 에펠, ALGOL 68, C1, C++, C#, Java, R, Erlang, 표준 ML, Javascript, MATLAB, Lisp, Lua, Scheme, OCaml, Haskell, Pascal, Perl, Ruby, PHP, Python, Smalltalk, Visual Basic .그물

에서 가져옴 단락 평가

VB.Net은 단락을 원하는지 여부에 따라 다른 구문을 가지고 있습니다.레거시 이유로 인해 기본 동작은 단락되지 않는 것입니다.구문은 다음과 같습니다

비 단락

IF A And B THEN
    ...
END IF

단락

IF A AndAlso B THEN
    ...
END IF

OR 문을 단락시키려면 Or / OrElse를 사용할 수 있습니다.다음과 같은 상황에서는 정말 좋습니다.

If MyObj IsNot Nothing AndAlso MyObj.Value < SomeValue Then
    ....
End If

개인적으로 나는 단락이 작업 속도를 높일 수 있다는 것을 이해하지만 코드만 보면 확실히 알 수 있는 것이 아닙니다.경험이 부족한 개발자가 이러한 행동에 혼란스러워하는 모습을 볼 수 있었습니다.최적화 수준에 대한 컴파일러 플래그에 따라 발생할 수도 있고 발생하지 않을 수도 있는 것처럼 보입니다.나는 VB가 실제로 달성하려는 동작에 대해 장황하게 설명하는 방식을 좋아합니다.

첫째, 친구가 틀렸습니다.단락 평가(최소 평가라고도 함)는 대부분의 언어에서 사용할 수 있으며 병렬 언어의 경우 중첩된 ifs보다 낫습니다(이 경우 반환되는 첫 번째 조건으로 인해 실행이 계속됩니다).

어쨌든 간단한 비병렬 언어에서도 첫 번째 조건이 평가될 때까지 실행이 차단되므로 중첩된 if가 얼마나 더 빠른지 알 수 없습니다.

정지되지 않으면 어떻게 중첩될 수 있습니까?실제로 a와 b가 모두 변수이고 부작용이 있는 표현식이 아닌 경우 좋은 컴파일러에 의해 병렬로 로드될 수 있습니다.줄 수를 늘리는 것 외에는 더 많은 if를 사용해도 이점이 없습니다.실제로 이것은 컴파일러를 추측하는 최악의 종류입니다.

이를 단락 평가라고 합니다.

내가 사용하는 유용한 단락은 다음과 같습니다.

if (a != null && a.equals(somevalue)) {
    ... do something.
}

제 생각에는 이것은 매우 읽기 쉽고 기능도 매우 좋습니다.일반적으로 나는 너무 많은 중첩을 피하려고 노력합니다. 왜냐하면 보기 흉한 코드로 이어지기 때문입니다.

하지만 모두 내 의견입니다.

대부분의 언어는 부울 표현식의 단락 평가를 수행합니다.나는 이것을 단락 평가(short-circuit Evaluation)라고 부르는 것을 항상 들어왔습니다.

질문의 예는 실제로 많은 성능 이점을 제공하지 않는 매우 단순한 예입니다.표현식을 평가하기 복잡할 때 성능상의 이점이 있습니다.

이것이 좋은 경우의 예로서 다음과 같은 게임 프로그램을 상상해보십시오.

if (someObject.isActive() && someOtherObject.isActive() && CollisionDetection.collides(someObject, someOtherObject) {
  doSomething();
}

이 경우 충돌 감지는 활성 검사보다 비용이 훨씬 더 많이 듭니다.시스템에 비활성 개체가 많으면 성능이 크게 향상됩니다.

단락 또는 최소 평가는 중첩된 if의 구문 설탕일 뿐입니다.비효율적이라고 가정하거나 지연을 초래하는 것은 조기 최적화의 경우입니다.이 시점에서 대부분의 컴파일러는 이러한 명령문을 올바르게 해석하고 최적화할 수 있을 만큼 지능적입니다.이러한 문을 사용하면 중첩이 크게 줄어들 수 있으므로 코드 가독성이 향상됩니다. 이는 최고의 목표입니다.

단락이 효율적인지 여부와 관련하여 파이프라이닝은 성능에 큰 영향을 미치지 않을 것입니다.영향을 미칠 수 있는 상황에서는 이러한 테스트에 부작용이 없는 한 컴파일러가 여러 조건을 병렬로 테스트하는 것을 막을 수 없습니다.또한 최신 CPU에는 분기 코드의 파이프라인 성능을 향상시키는 데 유용한 여러 메커니즘이 있습니다.

중첩된 if는 && 단락과 동일한 효과를 갖습니다.

'단락 평가'는 가장 일반적인 이름이며, 귀하의 친구는 이것이 흔하지 않다고 틀렸습니다.그것은 매우 흔한 일입니다.

나는 파이프라이닝에 대해 아무것도 모르지만, 단락 평가는 많은 언어의 공통 기능입니다(그리고 제가 아는 이름이기도 합니다).C에서 && 및 기타 연산자는 시퀀스 포인트 ;따라서 단락 평가가 여러 문을 사용하는 것보다 얼마나 덜 효율적인지 알 수 없습니다.

나는 그것을 단락이라고만 들었습니다.파이프라인에서 다음 작업은 if 문의 결과에 따라 달라지지 않나요?그렇다면 더 최적화되어 매번 두 값을 테스트할 필요가 없습니다.

단일 스레드는 순차적이므로 두 개의 if가 있는 경우 첫 번째는 물론 두 번째보다 먼저 평가되므로 차이점을 볼 수 없습니다.나는 중첩된 ifs보다 조건부 AND 연산자(&&를 afaik이라고 함)를 훨씬 더 많이 사용합니다.평가하는 데 시간이 걸릴 수 있는 항목을 확인하려면 먼저 간단한 테스트를 수행한 다음 조건부 및 이후에 더 어려운 테스트를 수행합니다.

a = obj.somethingQuickToTest() && obj.somethingSlowToTest();

와 별 다를게 없는 것 같다

a = false;
if(obj.somethingQuickToTest())
   a = obj.somethingSlowToTest();

문맥에 따라서는 "가드(Guarding)"라고도 부를 수 있습니다.

그리고 저는 제가 일했던 거의 모든 언어에서 그것을 보았습니다. 그 수는 거의 12개에 달합니다.

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