C++ async 仅使用 2 个内核

Posted

技术标签:

【中文标题】C++ async 仅使用 2 个内核【英文标题】:C++ async only uses 2 cores 【发布时间】:2014-06-05 19:59:01 【问题描述】:

我正在使用异步同时运行一个方法,但是当我检查我的 CPU 时,它显示只有 8 个中的 2 个在使用中。我的 CPU 利用率一直在 13%-16% 左右。 函数 async 应该在每次调用时创建一个新线程,因此应该能够使用更多处理器,还是我理解错误?

这是我的代码:

for (map<string, Cell>::iterator a = cells.begin(); a != cells.end(); ++a)

    for (map<string, Cell>::iterator b = cells.begin(); b != cells.end(); ++b)
    
        if (a->first == b->first)
            continue;

        if (_paths.count("path_" + b->first + "_" + a->first) > 0)
        
            continue;
        

        tmp = "path_" + a->first + "_" + b->first;
        auto future = async(launch::async, &Pathfinder::findPath, this, &a->second, &b->second, collisionZone);
        _paths[tmp] = future.get();
    

我理解错了吗?

编辑:

谢谢大家,我现在明白了。我不知道,在未来调用 .get() 会等待它完成,这之后似乎是合乎逻辑的......

但是,我现在编辑了我的代码:

    for (map<string, Cell>::iterator a = cells.begin(); a != cells.end(); ++a)

    for (map<string, Cell>::iterator b = cells.begin(); b != cells.end(); ++b)
    
        if (a->first == b->first)
            continue;

        if (_paths.count("path_" + b->first + "_" + a->first) > 0)
        
            continue;
        

        tmp = "path_" + a->first + "_" + b->first;
        mapBuffer[tmp] = async(launch::async, &Pathfinder::findPath, this, &a->second, &b->second, collisionZone);
    


for (map<string, future<list<Point>>>::iterator i = mapBuffer.begin(); i != mapBuffer.end(); ++i)

    _paths[i->first] = i->second.get();

它有效。现在它正确地产生线程并使用我所有的 cpu 功率。你给我省了很多麻烦!再次感谢。

【问题讨论】:

我很确定操作系统做出的决定(在语言级别)无法保证。 “我理解错了吗?” Yes, you did. 在生成 future 之后,您就正在收获它。 ^如果你不想“收获”它,你必须自己产生异步线程 【参考方案1】:

回答根本问题:

您可能应该通过拆分循环来重构代码。在第一个循环中,您创建所有期货并将它们放入由tmp 索引的地图中。在第二个循环中,您循环遍历此映射并获取每个未来的所有值,并将结果存储在 _paths

在第一个循环之后,您将有很多并行运行的期货,因此您的核心应该足够繁忙。如果cells 足够大(>numCores),最好只拆分内部循环。

【讨论】:

谢谢,您的回答给了我理解异步函数所需的最后一点。我还要感谢其他人。【参考方案2】:

std::async 异步运行指定函数并立即返回。就是这样。

如何做到这一点取决于编译器。一些编译器为每个异步操作创建线程,一些编译器有线程池。

我建议阅读:https://***.com/a/15775870/2786682

顺便说一句,您的代码并没有真正使用std::async,因为您在“生成”异步操作之后对future.get 进行同步调用。

【讨论】:

【参考方案3】:

是的,你确实弄错了。在编写任何代码之前,并行代码需要一些思考。

您的代码创建了一个future(它可能并且很可能会产生一个新线程),然后立即强制新创建的future 停止(调用它的.get()方法),进行同步,然后让它返回一个结果。

因此,通过这种策略,您的代码在任何时候都不会使用超过 2 个 CPU 内核。不能。

实际上,大多数时候您的代码只使用一个内核!

诀窍是“并行化”您的代码。

【讨论】:

以上是关于C++ async 仅使用 2 个内核的主要内容,如果未能解决你的问题,请参考以下文章

使用 c++ async 进行并行编程

多处理:仅使用物理内核?

C# Task.Run() 与 C++ std::async()

使用 std::async 时 C++“无法推断模板参数”

Linux 之父:C++语言很烂,不会改用其重写 Linux 内核

C++ - 使用 std::async 时显示进度条