I have been reading through the Optimizing C++ wikibook. In the faster operations chapter one of the advice is as follows:
Integer division by a constant
When you divide an integer (that is known to be positive or zero) by a constant, convert the integer to unsigned.
If s is a signed integer, u is an unsigned integer, and C is a constant integer expression (positive or negative), the operation s / C is slower than u / C, and s % C is slower than u % C. This is most significant when C is a power of two, but in all cases, the sign must be taken into account during division.
The conversion from signed to unsigned, however, is free of charge, as it is only a reinterpretation of the same bits. Therefore, if s is a signed integer that you know to be positive or zero, you can speed up its division using the following (equivalent) expressions: (unsigned)s / C and (unsigned)s % C.
I tested this statement with gcc and the u / C
expression seems to perform consistently better than the s / c
The following example is also provided below:
#include <iostream>
#include <chrono>
#include <cstdlib>
#include <vector>
#include <numeric>
using namespace std;
int main(int argc, char *argv[])
{
constexpr int vsize = 1e6;
std::vector<int> x(vsize);
std::iota(std::begin(x), std::end(x), 0); //0 is the starting number
constexpr int a = 5;
auto start_signed = std::chrono::system_clock::now();
int sum_signed = 0;
for ([[gnu::unused]] auto i : x)
{
// signed is by default
int v = rand() % 30 + 1985; // v in the range 1985-2014
sum_signed += v / a;
}
auto end_signed = std::chrono::system_clock::now();
auto start_unsigned = std::chrono::system_clock::now();
int sum_unsigned = 0;
for ([[gnu::unused]] auto i : x)
{
int v = rand() % 30 + 1985; // v in the range 1985-2014
sum_unsigned += static_cast<unsigned int>(v) / a;
}
auto end_unsigned = std::chrono::system_clock::now();
// signed
std::chrono::duration<double> diff_signed = end_signed - start_signed;
std::cout << "sum_signed: " << sum_signed << std::endl;
std::cout << "Time it took SIGNED: " << diff_signed.count() * 1000 << "ms" << std::endl;
// unsigned
std::chrono::duration<double> diff_unsigned = end_unsigned - start_unsigned;
std::cout << "sum_unsigned: " << sum_unsigned << std::endl;
std::cout << "Time it took UNSIGNED: " << diff_unsigned.count() * 1000 << "ms" << std::endl;
return 0;
}
You can compile and run the example here: http://cpp.sh/8kie3
Why is this happening?