(g ++ 4.6.3,cygwin,Windows 10)
我不确定是否有某种方法可以使用多线程机制加速以下程序(对此我很陌生):
// ab.h
class A {
// Member variables
...
// Member functions
A();
~A();
int foo_1();
void foo_2(std::vector<int>);
...
}
class B {
...
void schedule(std::vector<A>& va);
...
}
// b.cc
...
void B::schedule(std::vector<A>& va) {
std::vector<int> vc;
vc.resize(va.size());
for (... /* i from 0 to vc.size() */) {
...
vc[i] = va[i].foo_1();
...
}
for (... /* i from 0 to va.size() */) {
...
va[i].foo_2(vc);
...
}
// 5 more pairs of "for" loops like the above block
...
}
// main.cc
int main() {
...
std::vector<A> va;
// va.size() can be some large like 1000000
...
B b;
int simTime = 1000000000; // some large number of iterations
for (int clock = 0; clock != simTime; ++clock) {
b.schedule(va);
}
...
return 0;
}
所以基本上,我有一堆A
类型的对象,随着clock
的增长而“前进”,同时相互沟通。我担心的是:
for
和std::async
重写每个std::get()
循环对。这有效吗?我从某个地方听说std::async
最适合涉及长时间处理的函数(如I / O),因为构造/破坏线程的开销不可忽略(?)。但是,我的foo_1
和foo_2
功能不是那么“大”。我的代码运行时间很长(即使经过我自己的优化),同时还有一个功能强大的8核服务器......
答案 0 :(得分:4)
在CPU上使用8个内核并且只使用一个内核可能会浪费资源。所以你的问题是完全合理的。由于您只提供有关您的表现问题的信息,我只能给您一些一般性的想法。
多线程不一定是解决所有性能问题的最佳方法
如果您创建线程,则需要同步访问共享信息以避免数据争用。如果需要许多这样的同步,则存在线程之间存在争用的风险(即浪费时间等待其他线程准备好资源)。这可以轻松地让您从多线程中获益。
在您的特定情况下,两个循环都访问向量va
的相同元素。不幸的是,foo_1()
和foo2()
都没有被声明为const,这意味着它们可以修改向量的元素。所以你必须仔细检查这一点。
多线程提高了吞吐量,而不是执行时间
如果你使用所有8个内核,你会发现每个内核比执行相同的非线程代码要慢一些。幸运的是,如果每个线程彼此独立并且没有争用,那么整体吞吐量将是优越的(直言不讳地说:如果2个线程执行80%的非线程,则两者一起仍然是非线程的160%)
注意:如果您创建的线程数超过CPU可以处理的数量,则其他线程将不得不等待,并将创建额外的线程管理开销。这里有一个有用的指导由thread::hardware_concurrency()
给出(请记住,您的应用程序不是唯一可能创建线程的应用程序)。
武器的选择:Threadpools vs. std :: async
如果您在开头创建一个线程池,那么优势在于您已准备好触发许多线程。这可以避免在时间紧急情况下的线程创建开销。请记住,如果您处于硬件支持的线程范围内(除非您有大量的等待或IO延迟),这种好处才是真实的。
另一方面,使用std::async
,您将掌握在C ++实现中。例如,MSVC上的some experimentation表明,Microsoft的异步显然重用了它创建的线程,以避免创建开销。这种方法减少了太多的线程,并且在某些情况下表现优于线程池。
<强>结论:强>
由于性能取决于您的算法(主要),CPU线程,操作系统,编译器+标准库,我强烈建议您选择最佳方法进行一些基准测试/分析。