From 940f39e794e70620ab8e8f4a465029a8e8b6306d Mon Sep 17 00:00:00 2001 From: Deyi Chen Date: Tue, 16 Jun 2026 20:35:56 +0800 Subject: [PATCH] complete hw06 --- main.cpp | 144 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 106 insertions(+), 38 deletions(-) diff --git a/main.cpp b/main.cpp index a1d2625..aa81a3c 100644 --- a/main.cpp +++ b/main.cpp @@ -6,86 +6,154 @@ #include #include "ticktock.h" +#include + // TODO: 并行化所有这些 for 循环 template -std::vector fill(std::vector &arr, Func const &func) { +std::vector fill(std::vector &arr, Func const &func) +{ TICK(fill); - for (size_t i = 0; i < arr.size(); i++) { - arr[i] = func(i); - } + tbb::parallel_for( + tbb::blocked_range(0, arr.size()), + [&](tbb::blocked_range r) + { + for (size_t i = r.begin(); i < r.end(); i++) + { + arr[i] = func(i); + } + }); TOCK(fill); return arr; } template -void saxpy(T a, std::vector &x, std::vector const &y) { +void saxpy(T a, std::vector &x, std::vector const &y) +{ TICK(saxpy); - for (size_t i = 0; i < x.size(); i++) { - x[i] = a * x[i] + y[i]; - } + tbb::parallel_for( + tbb::blocked_range(0, x.size()), + [&](tbb::blocked_range r) + { + for (size_t i = r.begin(); i < r.end(); i++) + { + x[i] = a * x[i] + y[i]; + } + }); TOCK(saxpy); } template -T sqrtdot(std::vector const &x, std::vector const &y) { +T sqrtdot(std::vector const &x, std::vector const &y) +{ TICK(sqrtdot); - T ret = 0; - for (size_t i = 0; i < std::min(x.size(), y.size()); i++) { - ret += x[i] * y[i]; - } + // parallel_reduce(range, identity, body, combiner) + T ret = tbb::parallel_reduce( + tbb::blocked_range(0, std::min(x.size(), y.size())), + T(0), + [&](tbb::blocked_range r, T local) { // T local is local accumulator for every thread + for (size_t i = r.begin(); i < r.end(); i++) + { + local += x[i] * y[i]; + } + return local; + }, + std::plus()); ret = std::sqrt(ret); TOCK(sqrtdot); return ret; } template -T minvalue(std::vector const &x) { +T minvalue(std::vector const &x) +{ TICK(minvalue); - T ret = x[0]; - for (size_t i = 1; i < x.size(); i++) { - if (x[i] < ret) - ret = x[i]; - } + T ret = tbb::parallel_reduce( + tbb::blocked_range(0, x.size()), + std::numeric_limits::max(), // set to infinity + [&](tbb::blocked_range r, T local) + { + for (size_t i = r.begin(); i < r.end(); i++) + { + if (x[i] < local) + { + local = x[i]; + } + } + return local; + }, + [](T a, T b) + { return std::min(a, b); }); TOCK(minvalue); return ret; } template -std::vector magicfilter(std::vector const &x, std::vector const &y) { +std::vector magicfilter(std::vector const &x, std::vector const &y) +{ TICK(magicfilter); std::vector res; - for (size_t i = 0; i < std::min(x.size(), y.size()); i++) { - if (x[i] > y[i]) { - res.push_back(x[i]); - } else if (y[i] > x[i] && y[i] > 0.5f) { - res.push_back(y[i]); - res.push_back(x[i] * y[i]); - } - } + std::mutex mtx; + tbb::parallel_for( + tbb::blocked_range(0, std::min(x.size(), y.size())), + [&](tbb::blocked_range r) + { + std::vector local; + local.reserve(r.size()*2); + for (size_t i = r.begin(); i < r.end(); i++) + { + if (x[i] > y[i]) + { + local.push_back(x[i]); + } + else if (y[i] > x[i] && y[i] > 0.5f) + { + local.push_back(y[i]); + local.push_back(x[i] * y[i]); + } + } + std::lock_guard lock(mtx); + res.insert(res.end(), local.begin(), local.end()); + }); TOCK(magicfilter); return res; } template -T scanner(std::vector &x) { +T scanner(std::vector &x) +{ TICK(scanner); - T ret = 0; - for (size_t i = 0; i < x.size(); i++) { - ret += x[i]; - x[i] = ret; - } + T ret=tbb::parallel_scan( + tbb::blocked_range(0, x.size()), + T(0), + [&](tbb::blocked_range r, T sum, bool is_final) + { + T tmp = sum; + for (size_t i = r.begin(); i < r.end(); i++) + { + tmp += x[i]; + if (is_final) + x[i] = tmp; + } + return tmp; + }, + std::plus() + ); TOCK(scanner); return ret; } -int main() { - size_t n = 1<<26; + +int main() +{ + size_t n = 1 << 26; std::vector x(n); std::vector y(n); - fill(x, [&] (size_t i) { return std::sin(i); }); - fill(y, [&] (size_t i) { return std::cos(i); }); + fill(x, [&](size_t i) + { return std::sin(i); }); + fill(y, [&](size_t i) + { return std::cos(i); }); saxpy(0.5f, x, y);