Daily bit(e) C++ #68, Обобщенный алгоритм преобразования и сокращения C++17: std::transform_reduce
Преобразование-уменьшение — обычная операция в распределенных системах. В C++17 добавлена поддержка одноименного алгоритма, который предлагает шаблон преобразования-уменьшения для диапазонов.
Алгоритм требует коммутативной и ассоциативной редукции, но предлагает варианты с одним и двумя диапазонами и параллельные перегрузки.
#include <numeric> #include <vector> #include <execution> std::vector<double> values{2.3, 9.1, 4.7, 7.1, 1.9, 5.2}; std::vector<double> predictions{1.0, 2.0, 3.0, 4.0, 5.0, 6.0}; // Calculate the mean square error: auto mse = std::transform_reduce( values.begin(), values.end(), // all elements predictions.begin(), // first element from second range 0., // starting value, also dictates the type of accumulator std::plus<>{}, // reduction operation [](double val, double pred) { // transform operation return (val-pred)*(val-pred); }) / values.size(); // calculate the mean // Same, but computed in parallel. auto mse_par = std::transform_reduce(std::execution::par_unseq, values.begin(), values.end(), predictions.begin(), 0., std::plus<>{}, [](double val, double pred) { return (val-pred)*(val-pred); }) / values.size(); // mse == mse_par == 12.475 std::vector<int> data{1,2,3,4,5}; // Unary (single-range) version is also supported: int sum_of_squares = std::transform_reduce(data.begin(), data.end(), 0, std::plus<>{}, [](int v) { return v*v; }); // sum_of_squares == 55