1. Vấn đề nó giải quyết
Numeric workload cần reduction có thể reorganize hoặc chạy dưới execution policy, cùng operation fuse transform-and-reduce như dot product. C++17 chuẩn hóa cả hai.
2. Kiến thức cần có
Compiler hỗ trợ C++17, được gọi với warning đầy đủ, cùng các bài trước theo thứ tự của khóa học.
Biết
std::accumulate, associativity, floating-point rounding, iterator và binary operation.
3. Ý tưởng cốt lõi
std::reduce kết hợp range và có thể group operation theo order không quy định. std::transform_reduce transform input tương ứng rồi reduce result, có thể cho fusion và parallel execution.
4. Cú pháp tối thiểu
auto total = std::reduce(first, last, init);
auto dot = std::transform_reduce(a.begin(), a.end(),
b.begin(), 0);5. Cách nó hoạt động
Một integer vector được reduce thành sum, rồi hai vector được transform theo cặp bằng multiplication và reduce.
Integer addition vẫn exact trong range nên regrouping không quy định không thể đổi result cố định.
Chương trình in
sum: 10vàdot: 70, tạo test oracle nhỏ để so sánh với dự đoán trước khi biên dịch.
6. Lỗi thường gặp
Operation không associative hoặc floating-point addition có thể cho result khác khi reduction order đổi; không nên đặt side effect vào operation.
Build thành công chưa đủ; phải kiểm tra lifetime, ordering và error path.
7. Khi nào nên dùng
Nên dùng kỹ thuật này khi workload có thể reduce về toán học và regroup operation là chấp nhận được.
Nên chọn cách C++11/14 đơn giản hơn nếu quy tắc C++17 không cải thiện safety, độ rõ hoặc hiệu năng đã đo trên các toolchain phải hỗ trợ.
8. Ví dụ đơn giản
Dot product nhân phần tử tương ứng rồi cộng mà không cần intermediate vector. Integer nhỏ loại overflow khỏi bài.
Mã mẫu hoàn chỉnh
Tệp mã nguồn
cpp17/37_reduce_transform_reduce/main.cpp
#include <iostream>
#include <numeric>
#include <vector>
int main() {
const std::vector<int> left{1, 2, 3, 4};
const std::vector<int> right{5, 6, 7, 8};
const int total = std::reduce(left.begin(), left.end(), 0);
const int dot = std::transform_reduce(
left.begin(), left.end(), right.begin(), 0);
std::cout << "sum: " << total << '\n';
std::cout << "dot: " << dot << '\n';
}
9. Điều cần nhớ
Reduction cho phép reorder; hãy chọn operation và numeric type chịu được tự do đó.
Phải chọn rõ chế độ C++17; default của compiler mới hơn có thể che lỗi portability.
Warning và ví dụ xác định biến quy tắc ghi nhớ thành bằng chứng.
10. Câu hỏi tự kiểm tra
Dễ — std::reduce và std::transform_reduce giải quyết vấn đề chính nào?
Trung bình — Pairwise product nào góp vào dot product?
Khó — Vì sao
reducevàaccumulatecó thể khác với floating-point data?