Last active
November 22, 2023 16:52
-
-
Save kklobe/2df6ac7d485dce90a51c430c6fbdf978 to your computer and use it in GitHub Desktop.
Simple MPFR vs native double C++ benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <chrono> | |
#include <cmath> | |
#include <mpfr.h> | |
using namespace std::chrono; | |
// Prevent compiler optimizations | |
volatile double globalDouble; | |
volatile mpfr_t* globalMPFRPtr; | |
int64_t benchmarkDoubleArithmetic() { | |
double a = 1.23456789; | |
double b = 9.87654321; | |
double result = 0.0; | |
auto start = steady_clock::now(); | |
for (int i = 0; i < 1000000; ++i) { | |
result += a + b; | |
result += a - b; | |
result += a * b; | |
result += a / b; | |
} | |
auto stop = steady_clock::now(); | |
auto duration = duration_cast<microseconds>(stop - start); | |
// Prevent optimization | |
globalDouble = result; | |
return duration.count(); | |
} | |
int64_t benchmarkDoubleMathFunctions() { | |
double a = 1.23456789; | |
double result = 0.0; | |
auto start = steady_clock::now(); | |
for (int i = 0; i < 1000000; ++i) { | |
result += sqrt(a); | |
result += cos(a); | |
result += sin(a); | |
} | |
auto stop = steady_clock::now(); | |
auto duration = duration_cast<microseconds>(stop - start); | |
// Prevent optimization | |
globalDouble = result; | |
return duration.count(); | |
} | |
int64_t benchmarkMPFRArithmetic() { | |
mpfr_t a, b, result; | |
mpfr_init2(a, 80); // 80-bit precision | |
mpfr_init2(b, 80); | |
mpfr_init2(result, 80); | |
mpfr_set_d(a, 1.23456789, MPFR_RNDN); | |
mpfr_set_d(b, 9.87654321, MPFR_RNDN); | |
mpfr_t temp; | |
mpfr_inits2(80, temp, (mpfr_ptr) 0); | |
auto start = steady_clock::now(); | |
for (int i = 0; i < 1000000; ++i) { | |
mpfr_add(temp, a, b, MPFR_RNDN); | |
mpfr_add(result, result, temp, MPFR_RNDN); | |
mpfr_sub(temp, a, b, MPFR_RNDN); | |
mpfr_add(result, result, temp, MPFR_RNDN); | |
mpfr_mul(temp, a, b, MPFR_RNDN); | |
mpfr_add(result, result, temp, MPFR_RNDN); | |
mpfr_div(temp, a, b, MPFR_RNDN); | |
mpfr_add(result, result, temp, MPFR_RNDN); | |
} | |
auto stop = steady_clock::now(); | |
auto duration = duration_cast<microseconds>(stop - start); | |
// Prevent optimization | |
globalMPFRPtr = &result; | |
mpfr_clears(a, b, temp, (mpfr_ptr) 0); | |
return duration.count(); | |
} | |
int64_t benchmarkMPFRMathFunctions() { | |
mpfr_t a, result, temp; | |
mpfr_init2(a, 80); // 80-bit precision | |
mpfr_init2(result, 80); | |
mpfr_init2(temp, 80); | |
mpfr_set_d(a, 1.23456789, MPFR_RNDN); | |
auto start = steady_clock::now(); | |
for (int i = 0; i < 1000000; ++i) { | |
mpfr_sqrt(temp, a, MPFR_RNDN); | |
mpfr_add(result, result, temp, MPFR_RNDN); | |
mpfr_cos(temp, a, MPFR_RNDN); | |
mpfr_add(result, result, temp, MPFR_RNDN); | |
mpfr_sin(temp, a, MPFR_RNDN); | |
mpfr_add(result, result, temp, MPFR_RNDN); | |
} | |
auto stop = steady_clock::now(); | |
auto duration = duration_cast<microseconds>(stop - start); | |
// Prevent optimization | |
globalMPFRPtr = &result; | |
mpfr_clears(a, result, temp, (mpfr_ptr) 0); | |
return duration.count(); | |
} | |
int main() { | |
const auto time_native_arithmetic = benchmarkDoubleArithmetic(); | |
const auto time_native_math = benchmarkDoubleMathFunctions(); | |
const auto time_mpfr_arithmetic = benchmarkMPFRArithmetic(); | |
const auto time_mpfr_math = benchmarkMPFRMathFunctions(); | |
std::cout << "Native (double) arithmetic: " << time_native_arithmetic << " microseconds" << std::endl; | |
std::cout << "Native (double) math functions: " << time_native_math << " microseconds" << std::endl; | |
std::cout << "MPFR (80-bit) arithmetic: " << time_mpfr_arithmetic << " microseconds" << std::endl; | |
std::cout << "MPFR (80-bit) math functions: " << time_mpfr_math << " microseconds" << std::endl; | |
std::cout << "ratio of MPFR/native arithmetic: " << time_mpfr_arithmetic / time_native_arithmetic << std::endl; | |
std::cout << "ratio of MPFR/native math functions: " << time_mpfr_math / time_native_math << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment