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# Task.Run() 与 C++ std::async()