【问题标题】:Pass a template to an async function将模板传递给异步函数
【发布时间】:2021-12-29 05:14:57
【问题描述】:

我正在尝试运行一个异步函数,向它传递一个要执行的函数 f 和一个模板函数 f0 作为属性。

这是我通过模板创建的函数

DivideVerticesInThreads<0> f0(g, {}, {});

模板是

template <int NSegments, int Segment> struct SegmentVertices {
std::hash<Graph::vertex_descriptor> _h;
bool operator()(Graph::vertex_descriptor vd) const { return (_h(vd) % NSegments) == Segment; }
};

template <int N>
using DivideVerticesInThreads = boost::filtered_graph<Graph, boost::keep_all, SegmentVertices<4, N>>;

那我就这样调用async函数

auto handle = async(std::launch::async,f, f0);

然后我将函数 f 传递给它:

auto f = [&](G const& f0) {

    for(vp = vertices(f0); vp.first != vp.second; ++vp.first){
        //...
    }
};

完整的代码是:

template<typename G>
void parallel_count_adj_luby(G g){


    property_map<Graph,vertex_degree_t>::type deg = get(vertex_degree, g);


    auto f = [&](G const& g1) {

        for(vp = vertices(g1); vp.first != vp.second; ++vp.first){
            // ...
        }
    };

    DivideVerticesInThreads<0> f0(g, {}, {});

    auto handle = async(std::launch::async,f, f0);

}

问题是异步函数给了我这个错误

error: no matching function for call to 'async(std::launch, parallel_count_adj_luby(G) [with G = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, boost::property<boost::vertex_color_t, int, boost::property<boost::vertex_degree_t, int> > >]::<lambda(const boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, boost::property<boost::vertex_color_t, int, boost::property<boost::vertex_degree_t, int> > >&)>&, DivideVerticesInThreads<0>&)'
         auto handle = async(std::launch::async,f, f0);

我不太了解 c++ 和未来,所以错误可能是虚拟的。我做错了什么?

【问题讨论】:

  • G 中的auto f = [&amp;](G const&amp; f0) 是什么?
  • GDivideVerticesInThreads&lt;0&gt; 一样吗? (请阅读minimal reproducible example。)
  • G 只是一个模板 请放弃半解释并发布minimal reproducible example。另外,发布完整的编译器错误。 async 是什么?
  • 我希望我添加所有,尊重minimal reproducible example
  • 根据错误DivideVerticesInThreads&lt;0&gt; 不是G 也不能隐式转换为它。

标签: c++ asynchronous boost future


【解决方案1】:

我有点同意评论者的观点,即the problem exposition is needlessly unclear。¹

但是,我想我知道发生了什么是由于我在 presenting this sample code to you in an earlier answer 时所做的选择。

看来我专注于效率,它让你遇到了你不知道如何处理的 C++ 挑战。

我将忽略混淆并删除带有运行时参数的静态类型参数。这样,您过滤的图形段都可以具有相同的静态类型

Live On Compiler Explorer

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <boost/graph/random.hpp>
#include <iostream>
#include <random>

static std::mt19937 s_prng(std::random_device{}());

using G = boost::adjacency_list<>;
using V = G::vertex_descriptor;

struct SegmentVertices {
    unsigned nsegments, segment;

    bool operator()(V vd) const {
        return (std::hash<V>{}(vd) % nsegments) == segment;
    }
};

using F = boost::filtered_graph<G, boost::keep_all, SegmentVertices>;

G make_graph() {
    G g;
    generate_random_graph(g, 32 * 1024 - (s_prng() % 37), 64 * 1024, s_prng);
    return g;
}

void the_function(G const& g)
{
    std::cout << "Full graph " << size(boost::make_iterator_range(vertices(g)))
              << " vertices\n";
}

void the_function(F const& f)
{
    auto& pred = f.m_vertex_pred;

    std::cout << pred.segment << "/" << pred.nsegments << " "
              << size(boost::make_iterator_range(vertices(f))) << " vertices\n";
}

int main()
{
    G g = make_graph();
    the_function(g);

    unsigned NSegments = s_prng() % 10 + 2;

    for (unsigned seg = 0; seg < NSegments; ++seg) {
        the_function(F(g, {}, {seg, NSegments}));
    }
}

打印例如

Full graph 32736 vertices
0/3 10912 vertices
1/3 10912 vertices
2/3 10912 vertices

或者

Full graph 32741 vertices
0/7 4678 vertices
1/7 4678 vertices
2/7 4677 vertices
3/7 4677 vertices
4/7 4677 vertices
5/7 4677 vertices
6/7 4677 vertices

如您所见,使用运行时过滤器参数以性能换取运行时灵活性和类型便利性。


¹ 例如即使是第一个声明“这是我通过模板创建的函数”也是没有意义的,因为接下来的不是函数,也没有使用模板来创建它。

【讨论】:

    猜你喜欢
    • 2020-08-03
    • 2015-12-01
    • 2017-12-25
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多