Click here to Skip to main content
15,860,972 members
Articles / Programming Languages / Markdown
Tip/Trick

C++11 std::div() Benchmark

Rate me:
Please Sign up or sign in to vote.
4.56/5 (4 votes)
15 Jan 2019CPOL1 min read 15K   52   4   13
C++11 std::div() Benchmark

Update: rand() overhead in benchmark has been removed by filling the array with random values beforehand.

C++11 standard introduces std::div() and its siblings on the premise of some compiler can take advantage of the available machine code that compute quotient and remainder of division together. The C++ reference noted, and (updated) according to Petr Kobalíček, this function was never about performance but rounding direction of negative operands. We thank him for his comment.

Until C++11, the rounding direction of the quotient and the sign of the remainder in the built-in division and remainder operators was implementation-defined if either of the operands was negative, but it was well-defined in std::div.

On many platforms, a single CPU instruction obtains both the quotient and the remainder, and this function may leverage that, although compilers are generally able to merge nearby / and % where suitable.

We'll put std::div() to test in this benchmark.

Compiler Tested

  • GCC 7.4.0 on Cygwin
  • Clang 5.0.1 on Cygwin
  • Visual C++ 15.9 Update

OS: Windows 10 Pro

CPU: Intel i76820HQ

Loops: 10 million

Benchmark Code

C++
stopwatch.start("Division and Modulus");
for (size_t i = 0; i < vec.size(); ++i)
{
    TwoNum& a = vec[i];
    result.quot = a.num / a.divisor;
    result.rem = a.num % a.divisor;
    total_result += result.quot + result.rem; // prevent optimize away
}
stopwatch.stop();

total_result = 0L;
stopwatch.start("Custom div function");
for (size_t i = 0; i < vec.size(); ++i)
{
    TwoNum& a = vec[i];
    result = my_div(a.num, a.divisor);
    total_result += result.quot + result.rem; // prevent optimize away
}
stopwatch.stop();

total_result = 0L;
stopwatch.start("std::div function");
for (size_t i = 0; i < vec.size(); ++i)
{
    TwoNum& a = vec[i];
    result = std::div(a.num, a.divisor);
    total_result += result.quot + result.rem; // prevent optimize away
}
stopwatch.stop();

Custom my_div() function is defined as below:

C++
inline std::div_t my_div(int number, int divisior)
{
    return std::div_t{ (number / divisior), (number % divisior) };
}

Unoptimized Benchmark

GCC Unoptimized
Division and Modulus timing:108ms
Custom div function timing:150ms
std::div function timing:104ms

Clang Unoptimized
Division and Modulus timing:104ms
Custom div function timing:184ms
std::div function timing:102ms

VC++ Unoptimized
Division and Modulus timing:411ms
Custom div function timing:465ms
std::div function timing:427ms

On unoptimized GCC and Clang binary, std::div() is faster than my_div() and slightly faster than the individual division and modulus. For VC++, individual division and modulus is faster probably due to no overhead of function call.

Optimized Benchmark

GCC Optimized(O3)
Division and Modulus timing:30ms
Custom div function timing:34ms
std::div function timing:56ms

Clang Optimized(O3)
Division and Modulus timing:31ms
Custom div function timing:32ms
std::div function timing:54ms

VC++ Optimized(Ox)(Ot)
Division and Modulus timing:32ms
Custom div function timing:41ms
std::div function timing:50ms

On optimized binary, it is a shame that std::div() is consistently slower. In conclusion, today's compiler already does a very good job of computing division and modulus together without resorting to std::div() but it still has the performance lead when it comes to unoptimized build.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Singapore Singapore
Shao Voon is from Singapore. His interest lies primarily in computer graphics, software optimization, concurrency, security, and Agile methodologies.

In recent years, he shifted focus to software safety research. His hobby is writing a free C++ DirectX photo slideshow application which can be viewed here.

Comments and Discussions

 
Questionquotient and modulus together Pin
SeattleC++21-Jan-19 9:37
SeattleC++21-Jan-19 9:37 
Suggestionhints to make the benchmark better Pin
vickoza16-Jan-19 10:26
vickoza16-Jan-19 10:26 
AnswerRe: hints to make the benchmark better Pin
Shao Voon Wong16-Jan-19 15:45
mvaShao Voon Wong16-Jan-19 15:45 
SuggestionDifferences in rand() implementation should be affecting too much Pin
Armando A Bouza15-Jan-19 8:59
Armando A Bouza15-Jan-19 8:59 
AnswerRe: Differences in rand() implementation should be affecting too much Pin
Shao Voon Wong15-Jan-19 15:56
mvaShao Voon Wong15-Jan-19 15:56 
GeneralRe: Differences in rand() implementation should be affecting too much Pin
Armando A Bouza15-Jan-19 22:57
Armando A Bouza15-Jan-19 22:57 
Great, removing rand() overhead was very good.
I compiled and ran your new code with VC 14.0...
Timing: 47, 68, 87 ms
After changing /O2 to /Ox :
Timing: 38, 65, 85 ms

I also compiled with Intel Parallel Studio 2017, with /O3 and /arch:SSE3
Timing: 33, 35, 73 ms
Intel Parallel Studio 2017, with /O3 and /arch:AVX
Timing: 26, 27, 71 ms.

Moving to other CPU, 7820X, with AVX2 and AVX512, using Intel Parallel Studio 2017, I got:
For AVX: 22, 19, 53 ms
For AVX2: 11, 11, 53 ms
AVX-512: 12, 12, 61 ms

Intel Compiler generate significant better code if targeting AVX and even better for AVX2. Using AVX-Core-512 did not improved over AVX2, on the contrary it produced a slower executable.

So, using std::div is consistently bad.
Also, is good to note that for VC the maximum optimization level is /Ox, not /O2.

modified 16-Jan-19 8:39am.

Questionwhy is vc++ so slow? Pin
Satervalley14-Jan-19 16:40
Satervalley14-Jan-19 16:40 
AnswerRe: why is vc++ so slow? Pin
Member 1052334715-Jan-19 5:38
Member 1052334715-Jan-19 5:38 
GeneralRe: why is vc++ so slow? Pin
Michael Waters15-Jan-19 7:12
Michael Waters15-Jan-19 7:12 
AnswerRe: why is vc++ so slow? Pin
Shao Voon Wong15-Jan-19 15:20
mvaShao Voon Wong15-Jan-19 15:20 
GeneralRe: why is vc++ so slow? Pin
degski15-Jan-19 19:21
degski15-Jan-19 19:21 
GeneralRe: why is vc++ so slow? Pin
Shao Voon Wong16-Jan-19 13:51
mvaShao Voon Wong16-Jan-19 13:51 
GeneralRe: why is vc++ so slow? Pin
degski16-Jan-19 17:56
degski16-Jan-19 17:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.