Skip to content

Instantly share code, notes, and snippets.

@smoge
Last active May 21, 2024 10:50
Show Gist options
  • Save smoge/a26b595a7f9132458f3295de5d12a5f5 to your computer and use it in GitHub Desktop.
Save smoge/a26b595a7f9132458f3295de5d12a5f5 to your computer and use it in GitHub Desktop.
sum7.cpp
#include <algorithm>
#include <chrono>
#include <cmath>
#include <execution>
#include <iostream>
#include <numeric>
#include <random>
#include <stdexcept>
#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,
double min_positive_value = 0.1) {
if (arr.empty())
return;
double min_value =
*std::min_element(std::execution::par, arr.begin(), arr.end());
if (min_value >= min_positive_value)
return;
double adjustment_value = min_positive_value - 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: 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: 8.725e-06s
// Adjustment time: 1.551e-06s
// Normalization time: 9.09e-07s
// Size: 10000
// Generation time: 8.6596e-05s
// Adjustment time: 1.4603e-05s
// Normalization time: 8.189e-06s
// Size: 100000
// Generation time: 0.000789011s
// Adjustment time: 0.000211625s
// Normalization time: 8.2258e-05s
// Size: 1000000
// Generation time: 0.00934652s
// Adjustment time: 0.00194809s
// Normalization time: 0.00119473s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment