2013-07-08 1 views
7

다음 줄에 짧은 버전

: aOn0 또는 1입니다프로세서가 실제로 0 또는 1로 곱셈을 계산합니까? 왜?

aData[i] = aData[i] + (aOn * sin(i)); 

경우, 프로세서가 실제로 곱셈을 수행 않거나 조건부 다른 결과 (0에 대한 0를 해결 않습니다 - 1에 대한 값)?

긴 버전

나는 부분적으로 Branch Prediction의 효과에 대한보고를 포함 알고리즘 성능의 일관성으로 찾고 있어요.

for (i = 0; i < iNumSamples; i++) 
    aData[i] = aData[i] + (aOn * sin(i)); 

은 (분기 예측 성능을 불안정하게 할 수있다)이 코드는보다 안정된 성능을 제공한다 :

가설이이 코드 aOn

for (i = 0; i < iNumSamples; i++) 
{ 
    if (aOn) 
     aData[i] = aData[i] + sin(i); 
} 

0 또는 1 하나 인, 다른 스레드가 루프를 실행하는 동안 토글 할 수 있습니다.

실제 조건부 연산 (위의 예에서는 + sin(i))는 이상의 처리를 포함하고 상태가 루프 내에 있어야하는 경우에는 (다만 하나 위의 예에서와 같은 조건의 다수가있다; 또한, aOn 변경이 있어야 루프 당 즉시 영향을 미치지 않음).

성능 일관성을 무시하면 두 옵션 간의 성능 절충은 if 문과 곱셈의 실행에 걸리는 시간입니다.

에 관계없이,이 프로세서가 10 같은 값에 대한 실제 곱셈을 수행하지 않을 경우, 첫 번째 옵션은 윈 - 윈 솔루션 (아무 분기 예측, 더 나은 성능을) 할 수 있다는 것을 발견하기 쉽습니다.

+0

이 컴파일러는 사람들을 최적화 할 가능성이 높습니다. – iamnotmaynard

+0

필자는 최적화 여부에 상관없이 확인을했으며, '0', '1'및 기타 숫자의 배수 사이의 상대적인 성능에는 아무런 차이가 없습니다 (최적화는 모든 경우에 대해 성능을 약간 향상시킵니다). 그렇다면 최적화가 프로세서가 곱셈을 수행하는지 여부와 정확히 어떤 관련이 있습니까? – Izhaki

+0

@iamnotmaynard 컴파일러는 aOn이 상수가 아니라면 OP를 최적화 할 수는 없지만 OP가 그 값을 나타내지는 않습니다. –

답변

6

프로세서는 01으로 정규 승수를 수행합니다.

이유는 프로세서가 각 계산 전에 01을 확인하면 조건의 도입에 더 많은 시간이 걸릴 것입니다. 01 배율에 대한 성능을 얻는 동안 다른 값에 대해서는 성능이 떨어집니다 (가능성이 훨씬 높습니다). 이 증명할 수

간단한 프로그램 : 출력이

#include <iostream> 
#include "cycle.h" 
#include "time.h" 

void Loop(float aCoefficient) 
{ 
    float iSum = 0.0f; 

    clock_t iStart, iEnd; 

    iStart = clock(); 
    for (int i = 0; i < 100000000; i++) 
    { 
     iSum += aCoefficient * rand(); 
    } 
    iEnd = clock(); 
    printf("Coefficient: %f: %li clock ticks\n", aCoefficient, iEnd - iStart); 
} 

int main(int argc, const char * argv[]) 
{ 
    Loop(0.0f); 
    Loop(1.0f); 
    Loop(0.25f); 

    return 0; 
} 

하는 경우는 :

Coefficient: 0.000000: 1380620 clock ticks 
Coefficient: 1.000000: 1375345 clock ticks 
Coefficient: 0.250000: 1374483 clock ticks 
+0

어떤 최적화 수준을 사용했는지, 어떤 컴파일러를 사용했는지, 그리고 결과로 나온 'iSum'을 인쇄하여 시도했는지 - 더 중요한 것은 아마도'rand()'보다 약간 덜 집중적 인 것을 사용했을 것입니다. 컴파일러는'rand()'가 부작용 ('내부 상태를 수정한다') 때문에'rand()'를 호출했기 때문에 무엇이든 그것을 최적화 할 수는 없다. –

+0

좋은 점. 상대적 성능은 최적화 레벨에 관계없이 동일하게 유지됩니다 (none에서'-Os'). 컴파일러는 LLVM C++입니다. 'rand()'없이'iSum'을 출력하면 옵티 마이저가 루프를 건너 뛰는 것을 방지 할 수 있습니다. 'rand() '가없는 변형을 시도합니다. 예를 들어'sin (i)'으로 바꾸는 경우에도 여전히 3 개의 모든 승수에 대해 비슷한 결과가 나타납니다. – Izhaki

+0

컴파일러가 0.0 또는 1.0을 "곱하지 마십시오"로 미리 계산하는 시나리오를 얻는 것이 가능하다고 생각하지만, 동시에 컴파일러가 계수의 값을 상수로 볼 수있는 경우에만 가능합니다. 프로세서의 유형과 실행 중 가치의 예측 가능성에 따라 즉, 변경 빈도에 따라 '단순한'곱셈과 일반 곱셈을 비교하는 것이 더 나을 수도 있습니다. ... 계속 ... –