如何让函数根据向量大小返回std::execution执行策略?
针对std::execution策略选择的简洁解决方案
方法1:入口分支分发,避免循环内冗余判断
直接在处理逻辑的入口处根据向量总大小选择执行策略,分支仅存在于入口,循环内部无冗余判断,编译器可充分优化:
#include <execution> #include <vector> template <typename T, typename Func> void process_vector(std::vector<T>& vec, Func func) { // 可根据实际场景调整阈值(示例为1MB) const size_t threshold = 1024 * 1024; const size_t total_size = vec.size() * sizeof(T); if (total_size >= threshold) { std::for_each(std::execution::par, vec.begin(), vec.end(), func); } else { std::for_each(std::execution::seq, vec.begin(), vec.end(), func); } }
这种方式逻辑直观,运行时开销极小——仅一次大小判断,后续执行逻辑直接绑定对应策略,无额外分支。
方法2:用std::variant统一策略类型,通过std::visit调度
如果希望将策略选择与执行逻辑分离,可使用std::variant存储不同执行策略,再通过std::visit自动匹配对应执行逻辑:
#include <execution> #include <variant> #include <vector> // 定义包含两种策略的variant类型 using ExecutionPolicy = std::variant< std::execution::sequenced_policy, std::execution::parallel_policy >; // 根据总大小返回对应的策略variant ExecutionPolicy get_execution_policy(size_t total_size) { const size_t threshold = 1024 * 1024; return (total_size >= threshold) ? ExecutionPolicy(std::execution::par) : ExecutionPolicy(std::execution::seq); } // 使用示例 int main() { std::vector<int> vec = {/* 数据 */}; auto policy = get_execution_policy(vec.size() * sizeof(int)); std::visit([&](auto&& pol) { std::for_each(pol, vec.begin(), vec.end(), [](int& x) { x *= 2; }); }, policy); return 0; }
这种方式实现了策略选择与执行逻辑的解耦,std::visit会在编译期生成对应策略的执行代码,运行时无额外分支开销。
方法3:编译期判断(适用于大小固定的容器)
如果容器大小是编译期已知的(比如std::array),可使用if constexpr在编译阶段直接确定执行策略,彻底消除运行时分支:
#include <execution> #include <array> template <typename T, size_t N> void process_fixed_container(std::array<T, N>& arr) { if constexpr (N * sizeof(T) >= 1024 * 1024) { std::for_each(std::execution::par, arr.begin(), arr.end(), [](T& x) { /* 处理逻辑 */ }); } else { std::for_each(std::execution::seq, arr.begin(), arr.end(), [](T& x) { /* 处理逻辑 */ }); } }
编译器会根据模板参数N直接生成对应策略的代码,运行时无任何判断开销。
内容的提问来源于stack exchange,提问作者Bahram Gozalov
相关产品推荐
相关产品推荐

