处理器真的计算零或一的乘积吗?为什么?

Do processors actually calculate multiplication by a zero or one? Why?

本文关键字:为什么 真的 计算 处理器      更新时间:2023-10-16

短版本

在以下行中:

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

如果aOn01,处理器实际执行乘法,还是有条件地计算结果(001为其他值)?

长版本

我正在研究算法性能的一致性,这在一定程度上涉及到分支预测的效果。

假设这个代码:

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

将提供比此代码更稳定的性能(其中分支预测可能会破坏性能):

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

其中aOn01,并且它可以在另一个线程执行循环期间切换。

实际的条件计算(上例中的+ sin( i ))涉及更多的处理,if条件必须在循环中(有很多条件,而不仅仅是像上例中那样的一个;此外,对aOn的更改应该立即生效,而不是每个循环)。

忽略性能一致性,这两个选项之间的性能折衷在于执行if语句和乘法所需的时间。

无论如何,很容易发现,如果处理器不执行像10这样的值的实际乘法,那么第一个选项可能是双赢的解决方案(无分支预测,性能更好)。

处理器与0 s和1 s执行常规乘法运算。

原因是,如果处理器在每次计算之前检查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 ticksn", 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