运行时的不同执行策略 [英] Different execution policies at runtime

查看:109
本文介绍了运行时的不同执行策略的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++ 17中,algorithm标头中的许多函数现在可以采用执行策略.例如,我可以定义和调用这样的函数:

In C++17, a number of functions in the algorithm header now can take an execution policy. I can for example define and call a function like this:

template <class ExecutionPolicy>
void f1(const std::vector<std::string>& vec, const std::string& elem, ExecutionPolicy&& policy) {
    const auto it = std::find(
        std::forward<ExecutionPolicy>(policy),
        vec.cbegin(), vec.cend(), elem
    );
}

std::vector<std::string> vec;
f1(vec, "test", std::execution::seq);

但是,我还没有找到在运行时使用不同策略的好方法.例如,当我想根据某些输入文件使用其他策略时.

However I haven't found a good way to use different policies at runtime. For example when I want to use a different policy depending on some input file.

我玩弄各种变体,但最终问题始终是std::execution::seqstd::execution::parstd::execution::par_unseq的不同类型.

I toyed around with variants, but in the end the problem was always the different types of std::execution::seq, std::execution::par and std::execution::par_unseq.

一个可行但麻烦的解决方案如下:

A working but cumbersome solution would look like this:

void f2(const std::vector<std::string>& vec, const std::string& elem, const int policy) {
    const auto it = [&]() {
        if (policy == 0) {
            return std::find(
                std::execution::seq,
                vec.cbegin(), vec.cend(), elem
            );
        }
        else if (policy == 1) {
            return std::find(
                std::execution::par,
                vec.cbegin(), vec.cend(), elem
            );
        }
        else{
            return std::find(
                std::execution::par_unseq,
                vec.cbegin(), vec.cend(), elem
            );
        }
    };
}

f2(vec, "test", 0);

我还有其他更优雅的解决方案吗?

Is there any more elegant solution I'm overlooking?

也许我应该更精确些.假设目标是将策略保存在可以包含三个策略之一的变量中.该变量应该是函数的参数.

edit: maybe I should be more precise. Let's say the goal is to save the policy in a variable that can have either of the three policies. That variable should be a parameter to the function.

推荐答案

此处的标准方法是将类型的选择与类型的 use 分开:后者采用功能模板的形式,该功能模板由前一个非模板功能(或具有较少模板参数的功能模板)实例化了几次.

The standard approach here is to separate the selection of a type from the use of the type: the latter takes the form of a function template instantiated several times by the former non-template function (or function template with fewer template parameters).

为避免在这两层之间复制常规参数,请使用通用lambda作为模板.为避免重复选择逻辑,请制作一个函数模板,以适当的策略调用任何lambda:

To avoid duplicating the normal parameters between these two layers, use a generic lambda as the template. To avoid duplicating the selection logic, make a function template that calls whatever lambda with the appropriate policy:

enum Policy {seq,par,par_unseq};

template<class F>
auto maybe_parallel(F f,Policy p) {
  switch(p) {
  case seq: return f(std::execution::seq);
  case par: return f(std::execution::par);
  default: return f(std::execution::par_unseq);
  }
}

auto f2(const std::vector<std::string>& vec,
        const std::string& elem,Policy p) {
  return maybe_parallel
    ([&](auto &pol) {return std::find(pol,vec.begin(),vec.end(),elem);},p);
}

这篇关于运行时的不同执行策略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆