C++11异步只使用一个核心
C++11 async is using only one core
我试图在C++中并行化一个长时间运行的函数,并使用std::async,它只使用一个核心。
这并不是因为函数的运行时间太短,因为我目前使用的测试数据大约需要10分钟才能运行。
根据我的逻辑,我创建了相当于Futures的NThreads(每个线程占用循环的一部分,而不是一个单独的单元,因此它是一个运行时间很长的线程),每个线程都将调度一个异步任务。然后在它们被创建之后,程序旋转锁等待它们完成。然而,它总是使用一个核心?!
这也不是我看着顶部说它看起来大致像一个CPU,我的ZSH配置输出上一个命令的CPU%,它总是精确地100%,从未超过
auto NThreads = 12;
auto BlockSize = (int)std::ceil((int)(NThreads / PathCountLength));
std::vector<std::future<std::vector<unsigned __int128>>> Futures;
for (auto I = 0; I < NThreads; ++I) {
std::cout << "HERE" << std::endl;
unsigned __int128 Min = I * BlockSize;
unsigned __int128 Max = I * BlockSize + BlockSize;
if (I == NThreads - 1)
Max = PathCountLength;
Futures.push_back(std::async(
[](unsigned __int128 WMin, unsigned __int128 Min, unsigned__int128 Max,
std::vector<unsigned __int128> ZeroChildren,
std::vector<unsigned __int128> OneChildren,
unsigned __int128 PathCountLength)
-> std::vector<unsigned __int128> {
std::vector<unsigned __int128> LocalCount;
for (unsigned __int128 I = Min; I < Max; ++I)
LocalCount.push_back(KneeParallel::pathCountOrStatic(
WMin, I, ZeroChildren, OneChildren, PathCountLength));
return LocalCount;
},
WMin, Min, Max, ZeroChildInit, OneChildInit, PathCountLength));
}
for (auto &Future : Futures) {
Future.get();
}
有人有什么见解吗。
我正在Arch Linux上使用clang和LLVM进行编译。有没有我需要的编译标志,但从我能告诉C++11标准化了线程库的内容来看?
编辑:如果它能帮助任何人提供任何进一步的线索,当我注释掉局部向量时,它会在所有核心上运行,当我把它放回回滚到一个核心时。
编辑2:所以我确定了解决方案,但它看起来很奇怪。从lambda函数返回向量将其固定为一个核心,所以现在我通过向输出向量传递shared_ptr
并对其进行操作来绕过它。嘿,普雷斯托,它在核心上燃烧起来!
我觉得现在使用期货毫无意义,因为我没有回报,我会使用线程,不!,使用no返回的线程也使用一个核心。奇怪吧?
好吧,回到使用期货,只需返回一个into就可以扔掉什么的。是的,你猜对了,即使从线程中返回一个int,也会将程序粘在一个核心上。除了futures不能有void lambda函数。因此,我的解决方案是将一个指针传递给一个从不返回任何内容的int lambda函数来存储输出。是的,感觉像胶带,但我看不到更好的解决方案。
看起来很…奇怪?就像编译器在某种程度上解释lambda不正确一样。可能是因为我使用的是LLVM的开发版本,而不是一个稳定的分支。。。?
不管怎样,我的解决方案,因为我最讨厌的就是在这里找到我的问题,却没有答案:
auto NThreads = 4;
auto BlockSize = (int)std::ceil((int)(NThreads / PathCountLength));
auto Futures = std::vector<std::future<int>>(NThreads);
auto OutputVectors =
std::vector<std::shared_ptr<std::vector<unsigned __int128>>>(
NThreads, std::make_shared<std::vector<unsigned __int128>>());
for (auto I = 0; I < NThreads; ++I) {
unsigned __int128 Min = I * BlockSize;
unsigned __int128 Max = I * BlockSize + BlockSize;
if (I == NThreads - 1)
Max = PathCountLength;
Futures[I] = std::async(
std::launch::async,
[](unsigned __int128 WMin, unsigned __int128 Min, unsigned __int128 Max,
std::vector<unsigned __int128> ZeroChildren,
std::vector<unsigned __int128> OneChildren,
unsigned __int128 PathCountLength,
std::shared_ptr<std::vector<unsigned __int128>> OutputVector)
-> int {
for (unsigned __int128 I = Min; I < Max; ++I) {
OutputVector->push_back(KneeParallel::pathCountOrStatic(
WMin, I, ZeroChildren, OneChildren, PathCountLength));
}
},
WMin, Min, Max, ZeroChildInit, OneChildInit, PathCountLength,
OutputVectors[I]);
}
for (auto &Future : Futures) {
Future.get();
}
通过为async提供第一个参数,您可以将其配置为延迟运行(std::launch::deferred
)、在自己的线程中运行(std::launch::async
),或者让系统在这两个选项之间做出决定(std::launch::async | std::launch::deferred
)。后者是默认行为。
因此,要强制它在另一个线程中运行,请将std::async
的调用调整为std::async(std::launch::async, /*...*/)
。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 在多个核心中处理一个HTTP请求
- 为什么我的代码给我一个分段/核心转储错误?
- 在 "CodePad" 中执行链表操作时转储的核心(这是一个在线C++编译器)
- 将缓存线迁移到另一个核心
- 为什么装饰器模式实现需要一个具有核心类的公共抽象超类
- GDB正在调试一个缺少特定调用堆栈的符号表的核心转储
- 如何在另一个核心上启动线程而不将处理器亲和力设置为特定核心
- 让g++产生一个可以使用多核心的程序
- SmartPoint 在<C++primer>4th中的一个例子,它抛出核心转储
- C++11异步只使用一个核心
- OpenCV:试图创建一个空白图像,但核心已被转储
- list pushback一个包含字符串类型核心的结构
- 我运行一个程序并遇到分段错误(核心转储),我使用 gdb 进行调试,程序在运行 ui->setupUI() 时崩溃了
- 我怎么能得到一个过程到核心映射在C
- 我试图访问一个c++多态类的虚表,但失败的核心转储,为什么
- C 语言中的另一个核心转储问题
- 在Win32上,如何将线程移动到另一个CPU核心