2014-01-13 49 views
1

什么是效率最高如何从C++ 11中的线程返回值?从C++中的线程返回值11

vector<thread> t(6); 

for(int i = 0; i < 6; i++) 
    t[i] = thread(do_c); 

for(thread& t_now : t) 
    t_now.join(); 

for(int i = 0; i < 6; i++) 
    cout << /*the return of function do_c*/ 

另外,如果变化将有利于性能,随意推荐另一个线程比std::thread

+0

你不小心一个字?从线程返回值,对吗? –

+0

?你什么意思?是 – Luka

+0

是的,但我想最有效的方式 – Luka

回答

4

启动一个线程并终止它需要数百个机器周期。但这只是一个开始。线程之间的上下文切换(如果线程正在执行任何有用的事情时会发生)将重复消耗更多数百个机器周期。所有这些线程的执行上下文将消耗许多字节的内存,这反过来会弄乱许多行缓存,从而妨碍了CPU在数百个机器周期中的又一个很大的努力。事实上,多任务处理是数百个机器周期的一个重要消费者。多任务处理仅在CPU功耗方面变得有利可图当您设法获得足够的处理器以处理概念上独立的数据块(因此并行处理不会威胁到它们的完整性)并且大到足以显示净收益时与单处理器版本。

在所有其他情况下,多任务处理是在所有域,但一个固有低效:反应。任务可以对外部事件作出快速而准确的反应,最终来自外部H/W组件(无论是定时器的内部时钟还是用于网络流量的WiFi /以太网控制器)。

这种在不浪费CPU的情况下等待外部事件的能力是提高整体CPU效率的原因。就是这样。
在其他性能参数方面(内存消耗时间内核调用内部的浪费,等等),推出一个新的线程是总的净亏损

概括地说,多任务编程的技术归结为:

  • 识别所述外部I/O流,你将不得不处理
  • 考虑反应性的要求考虑(记住多个反应性=更少CPU /内存在99%的时间内高效运行)
  • 以合理的效率/易于维护的折中方式为所需事件设置处理程序。

多处理器架构正在增加一个新的复杂程度,因为现在任何程序都可以看作是一个拥有许多外部CPU的进程,可以用作额外的电源。但是你的问题似乎没有任何关系。

的多任务处理效率的量度,最终将取决于给定的计划预计以应付同时和一组给定的反应性限制外部事件数。

最后我来谈谈你的问题。

要应对外部事件,每一个新的树枝或死昆虫的位必须移动周围的蚁丘是一个非常粗糙和低效的进场时间发动的任务。

您在您的处置许多强大的同步工具,这将让你从(近)在(几乎)没有成本最优效率的单个任务范围内的是一帮异步事件的反应。
通常情况下,在多个输入阻塞等待,例如像Unix的口味select()或微软的WaitForMultipleEvents()对口。

使用这些会给你一个性能提升无比超过几十个CPU周期,你可以挤出你这个任务的结果收集优化项目的更大。

所以我的答案是:不要打扰优化线程设置。这不是问题。

你最好将时间花在重新考虑你的架构,这样经过深思熟虑的线程少数可以取代无用CPU成群的记忆猪当前的设计会催生。

+0

感谢您的解释,neko-san。这让我改变主意,决定不使用线程。 – Luka

+0

@Luka很高兴能够帮助您(和您的编译器以及您的CPU)带来许多不必要的痛苦;) –

+0

对不起,我错误地将您的帖子错误地提交了,请编辑它以注销它... – Luka

6

首先std::thread不会返回一个值,但是在构造时传递给它的函数可能会非常好。

没有办法从std::thread对象中访问函数的返回值,除非在线程上调用该函数后以某种方式保存它。

一个简单的解决方案,例如,将引用传递给线程并将结果存储在引用指向的内存中。对于线程,虽然必须注意不要引入数据竞赛

考虑一个简单的函数:

int func() { 
    return 1; 
} 

而且这个例子:

std::atomic<int> x{0}; // Use std::atomic to prevent data race. 

std::thread t{[&x] { // Simple lambda that captures a reference of x. 
    x = func();  // Call function and assign return value. 
}}; 

/* Do something while thread is running... */ 

t.join(); 

std::cout << "Value: " << x << std::endl; 

现在,而不是处理这个低级别的并发填充自己,你可以使用标准库有人(一如既往)已经为你解决了它。有std::packaged_taskstd::future这是设计与std::thread为这种特殊类型的问题。在大多数情况下,它们也应该是,就像高效的一样是自定义解决方案。

下面是使用std::packaged_taskstd::future等效例如:

std::packaged_task<int()> task{func}; // Create task using func. 
auto future = task.get_future();  // Get the future object. 

std::thread t{std::move(task)};  // std::packaged_task is move-only. 

/* Do something while thread is running... */ 

t.join(); 

std::cout << "Value: " << future.get() << std::endl; // Get result atomically. 

不要总是认为事情是仅仅因为它被认为是“高级别”低效率。

+0

我的脑海里浮现的问题是:什么*功能*要求将证明使用一种设计的机制可以在脑海中并行处理大量数据以检索单纯的整数线程返回值?看起来更像我称之为语法驱动的软件设计。随着C++ 11多功能性的展示,这些解决方案非常漂亮,但它们可以在语法糖,恕我直言的结冰下隐藏大量的资源消耗。 –

+0

@kuroineko这一切都取决于我猜的域名。对于通用应用程序开发,我将使用标准化的类和函数来实现同事间的最大可理解性,而不是定制解决方案。是否有任何功能需求来证明使用抽象?那么我想不出任何。但是缺乏功能性要求来证明抽象代码的可维护性并不是不那么重要。非功能性要求也很重要。 – Snps

+0

正如我所看到的,这是一个在易用性和浪费之间找到一个甜蜜点的问题,如果不是潜在危险的习惯。在那个具体情况下,我认为值得关于舒适性的价格有点值得思考。我确实设计了嵌入式软件十年左右,这可能是为什么看到投入这么多资源以避免这么小的努力往往会让我紧张:)。 –