Skip to content

Instantly share code, notes, and snippets.

@smoge
Last active May 21, 2024 10:23
Show Gist options
  • Save smoge/a5a213f7d7461c3a607ef6fedbc5bf76 to your computer and use it in GitHub Desktop.
Save smoge/a5a213f7d7461c3a607ef6fedbc5bf76 to your computer and use it in GitHub Desktop.
sum6.cpp
#include <algorithm>
#include <chrono>
#include <execution>
#include <iostream>
#include <numeric>
#include <random>
#include <vector>
class RandomNumberGenerator {
public:
RandomNumberGenerator() : gen_(std::random_device{}()), dis_(0.0, 100.0) {}
void generate(std::vector<double> &values) {
std::generate(values.begin(), values.end(),
[this]() { return dis_(gen_); });
}
private:
std::mt19937 gen_;
std::uniform_real_distribution<> dis_;
};
void adjust_to_positive(std::vector<double> &arr) {
auto min_value =
*std::min_element(std::execution::par, arr.begin(), arr.end());
double adjustment_value = 1.0 - min_value;
std::for_each(std::execution::par, arr.begin(), arr.end(),
[adjustment_value](double &val) { val += adjustment_value; });
}
void normalize_array(std::vector<double> &arr) {
const double sum =
std::reduce(std::execution::par, arr.begin(), arr.end(), 0.0);
const double epsilon = 1e-8;
if (std::abs(sum) <= epsilon) {
throw std::runtime_error(
"Cannot normalize array with sum too close to 0.0");
}
double inv_sum = 1.0 / sum;
std::for_each(std::execution::par, arr.begin(), arr.end(),
[inv_sum](double &val) { val *= inv_sum; });
}
int main() {
const size_t list_sizes[] = {1000, 10000, 100000, 1000000};
RandomNumberGenerator rng;
for (size_t n : list_sizes) {
std::vector<double> values(n);
auto start = std::chrono::high_resolution_clock::now();
rng.generate(values);
auto gen_end = std::chrono::high_resolution_clock::now();
auto adjust_start = std::chrono::high_resolution_clock::now();
adjust_to_positive(values);
auto adjust_end = std::chrono::high_resolution_clock::now();
normalize_array(values);
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> gen_duration = gen_end - start;
std::chrono::duration<double> adjust_duration = adjust_end - adjust_start;
std::chrono::duration<double> norm_duration = end - adjust_end;
std::cout << "Size: " << n << "\nGeneration time: " << gen_duration.count()
<< "s" << "\nAdjustment time: " << adjust_duration.count() << "s"
<< "\nNormalization time: " << norm_duration.count() << "s\n\n";
}
return 0;
}
Size: 1000
Generation time: 7.0092e-05s
Adjustment time: 1.217e-06s
Normalization time: 4.77e-07s
Size: 10000
Generation time: 0.000810673s
Adjustment time: 1.1917e-05s
Normalization time: 4.245e-06s
Size: 100000
Generation time: 0.00764328s
Adjustment time: 0.000131727s
Normalization time: 9.2728e-05s
Size: 1000000
Generation time: 0.0753062s
Adjustment time: 0.00181232s
Normalization time: 0.00111687s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment