Skip to content

Instantly share code, notes, and snippets.

@kklobe
Last active November 22, 2023 16:52
Show Gist options
  • Save kklobe/2df6ac7d485dce90a51c430c6fbdf978 to your computer and use it in GitHub Desktop.
Save kklobe/2df6ac7d485dce90a51c430c6fbdf978 to your computer and use it in GitHub Desktop.
Simple MPFR vs native double C++ benchmark
#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