are 2^n exponent calculations really less efficient than bit-shifts?

后端 未结 4 935
长情又很酷
长情又很酷 2020-12-15 21:01

if I do:

int x = 4;
pow(2, x);

Is that really that much less efficient than just doing:

1 << 4

?

4条回答
  •  萌比男神i
    2020-12-15 21:56

    Yes. Though by how much I can't say. The easiest way to determine that is to benchmark it.

    The pow function uses doubles... At least, if it conforms to the C standard. Even if that function used bitshift when it sees a base of 2, there would still be testing and branching to reach that conclusion, by which time your simple bitshift would be completed. And we haven't even considered the overhead of a function call yet.

    For equivalency, I assume you meant to use 1 << x instead of 1 << 4.

    Perhaps a compiler could optimize both of these, but it's far less likely to optimize a call to pow. If you need the fastest way to compute a power of 2, do it with shifting.

    Update... Since I mentioned it's easy to benchmark, I decided to do just that. I happen to have Windows and Visual C++ handy so I used that. Results will vary. My program:

    #include 
    
    #include 
    #include 
    #include 
    
    LARGE_INTEGER liFreq, liStart, liStop;
    
    
    inline void StartTimer()
    {
        QueryPerformanceCounter(&liStart);
    }
    
    
    inline double ReportTimer()
    {
        QueryPerformanceCounter(&liStop);
        double milli = 1000.0 * double(liStop.QuadPart - liStart.QuadPart) / double(liFreq.QuadPart);
        printf( "%.3f ms\n", milli );
        return milli;
    }
    
    
    int main()
    {    
        QueryPerformanceFrequency(&liFreq);
    
        const size_t nTests = 10000000;
        int x = 4;
        int sumPow = 0;
        int sumShift = 0;
    
        double powTime, shiftTime;
    
        // Make an array of random exponents to use in tests.
        const size_t nExp = 10000;
        int e[nExp];
        srand( (unsigned int)time(NULL) );
        for( int i = 0; i < nExp; i++ ) e[i] = rand() % 31;
    
        // Test power.
        StartTimer();
        for( size_t i = 0; i < nTests; i++ )
        {
            int y = (int)pow(2, (double)e[i%nExp]);
            sumPow += y;
        }
        powTime = ReportTimer();
    
        // Test shifting.
        StartTimer();
        for( size_t i = 0; i < nTests; i++ )
        {
            int y = 1 << e[i%nExp];
            sumShift += y;
        }
        shiftTime = ReportTimer();
    
        // The compiler shouldn't optimize out our loops if we need to display a result.
        printf( "Sum power: %d\n", sumPow );
        printf( "Sum shift: %d\n", sumShift );
    
        printf( "Time ratio of pow versus shift: %.2f\n", powTime / shiftTime );
    
        system("pause");
        return 0;
    }
    

    My output:

    379.466 ms
    15.862 ms
    Sum power: 157650768
    Sum shift: 157650768
    Time ratio of pow versus shift: 23.92
    

提交回复
热议问题