Last active
May 21, 2024 10:50
-
-
Save smoge/a26b595a7f9132458f3295de5d12a5f5 to your computer and use it in GitHub Desktop.
sum7.cpp
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 <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