并行模式库PPL应用实战(一):使用task类创建并行任务
自 VS2010 起,微软就在 CRT 中集成了并发运行时(Concurrency Runtime),并行模式库(PPL,Parallel Patterns Library)是其中的一个重要组成部分。7 年过去了,似乎大家都不怎么Care这个事情,相关文章少少且多是蜻蜓点水。实际上这个库的设计相当精彩,胜过 C++ 标准库中 future/promise/async 系列许多,所以计划写一个系列探讨 PPL 在实际项目中应用中的各种细节。
好了,从最简单的代码开始,先演示下如何使用 task 类和 lambda 表达式创建一个并行任务:
// final_answer.cpp
// compile with: /EHsc #include <ppltasks.h>
#include <iostream> using namespace concurrency;
using namespace std; int main(int argc, char *argv[])
{
task<int> final_answer([]
{
return ;
}); cout << "The final answer is: " << final_answer.get() << endl; return ;
}
使用 Visual Studio 命令行工具编译
cl /EHsc final_answer.cpp
执行结果为:
The final answer is: 42
task 类的原型如下:
template<typename _ReturnType>
class task;
其模板参数 _ReturnType 是任务返回值类型。 task:get 方法则用于获取返回值,原型如下:
_ReturnType get() const;
task 类的构造函数原型:
template<typename T>
__declspec(noinline) explicit task(T _Param);
可以看到这是个模板函数,其参数 _Param 可以是 lambda 表达式、函数对象、仿函数、函数指针等可以以 _Param() 形式调用的类型,或者 PPL 中的 task_completion_event<result_type> 类型。因此可以使用各种灵活的方式构造 task 对象,其中 lambda 表达式无疑是最方便常用的一种。
接下来我们修改上面的程序,打印出线程 id 以便观察并行任务的执行情况。
// final_answer_1.cpp
// compile with: /EHsc #include <ppltasks.h>
#include <iostream>
#include <thread> using namespace concurrency;
using namespace std; int main(int argc, char *argv[])
{
cout << "Major thread id is: " << this_thread::get_id() << endl; task<int> final_answer([]
{
cout << "Thread id in task is:" << this_thread::get_id() << endl;
return ;
}); cout << "The final answer is: " << final_answer.get() << endl; return ;
}
继续编译执行,得到输出结果:
Major thread id is: 164824
Thread id in task is: 164824
The final answer is: 42
注意两个线程 id 是相同的,很有些意外,任务是在主线程执行的而非预计的其他后台工作线程。实际上这是 PPL 的优化策略造成的。
再修改下程序,在 task 对象构造完成后加一个 sleep 调用挂起当前线程一小段时间:
int main(int argc, char *argv[])
{
cout << "Major thread id is: " << this_thread::get_id() << endl; task<int> final_answer([]
{
cout << "Thread id in task is:" << this_thread::get_id() << endl;
return ;
}); this_thread::sleep_for(chrono::milliseconds()); cout << "The final answer is: " << final_answer.get() << endl; return ;
}
这次输出结果发生了变化:
Major thread id is: 173404
Thread id in task is: 185936
The final answer is: 42
PPL 使用了一个新的线程执行并行任务,实际上 PPL 是使用了线程池来执行被调度到的任务。
而在上一个程序中,由于没有 sleep,也没有其他耗时的代码,执行到 task::get 方法时并行任务尚未被调度所以直接在当前线程执行该任务,这样就节省了两次线程切换的开销。
MSDN 中对 task::wait 方法的说明:
It is possible for wait to execute the task inline, if all of the tasks dependencies are satisfied, and it has not already been picked up for execution by a background worker.
task::get 方法的内部实现会先调用 task::wait 方法所以有同样的效果。
本章小结:
1. task 类对象构造完成后即可被调度执行;
2. 并行有可能被优化在当前线程执行;
留一个问题,如果 task 对象构造后马上析构,该并行任务是否会被调度执行呢?
本章代码使用 visual studio community 2013 编译调试通过。
本章参考文档:
How to: Create a Task that Completes After a Delay
task Class (Concurrency Runtime)
并行模式库PPL应用实战(一):使用task类创建并行任务的更多相关文章
- .NET并行编程1 - 并行模式
设计模式——.net并行编程,清华大学出版的中译本. 相关资源地址主页面: http://parallelpatterns.codeplex.com/ 代码下载: http://parallelpat ...
- 有助于提高你的 Web 开发技能的7个模式库
正如语言风格指南一样,模式库有两个主要用途.首先,是它们提供了一组编码或设计标准,Web 开发团队可以在整个网站中应用,有助于保持一致的编码实践和外观:其次,对于要学习网页设计最佳实践来说是宝贵的财富 ...
- Java多线程--并行模式与算法
Java多线程--并行模式与算法 单例模式 虽然单例模式和并行没有直接关系,但是我们经常会在多线程中使用到单例.单例的好处有: 对于频繁使用的对象可以省去new操作花费的时间: new操作的减少,随之 ...
- 并行模式之Guarded Suspension模式
并行模式之Guarded Suspension模式 一).Guarded Suspension: 保护暂存模式 应用场景:当多个客户进程去请求服务进程时,客户进程的请求速度比服务进程处里请求的速度快, ...
- 并行模式之Master-Worker模式
并行模式之Master-Worker模式 一).Master-Worker模式 作用: 将一个大任务分解成若干个小任务,分发给多个子线程执行. 注: 将大任务分解成小任务,小任务的实现逻辑要相同. 二 ...
- oracle并行模式
参考链接:oracle并行模式(Parallel),深入理解Oracle的并行操作(原创),oracle使用并行踩过的坑 1. 语法(这个可以加到insert.delete.update.select ...
- 【C/C++开发】C++静态库与动态库以及在Linux和Windows上的创建使用
原文出处: 吴秦的博客 这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学 ...
- .NET 4 并行(多核)编程系列之三 从Task的取消
原文:.NET 4 并行(多核)编程系列之三 从Task的取消 .NET 4 并行(多核)编程系列之三 从Task的取消 前言:因为Task是.NET 4并行编程最为核心的一个类,也我们在是在并行编程 ...
- SSIS从理论到实战,再到应用(1)----创建自己的第一个包
原文:SSIS从理论到实战,再到应用(1)----创建自己的第一个包 其实,如果你使用sql2008的导出导入工具的时候,你就已经在使用包了. 目标:使用sql2008 导入导出工具,导入excel数 ...
随机推荐
- HTML5 拖放(Drag 和 Drop)功能开发——浅谈dataTransfer对象
[前言] 之前我已经为大家介绍过一篇有关HTML5中原生拖拽的相关知识了.今天为大家介绍HTML5拖拽中的其他一些关于dataTransfer对象的知识和应用. dataTransfer对象 之前的一 ...
- Android ViewPager动画切换
使用方法 setPageTransformer 例如: ViewPager.setPageTransformer(true, new ZoomOutPageTransformer()) package ...
- 一句话告诉你JQuery $(this)到底指的是什么,怎么用
看了网上好多关于jquery $(this)的解释,感觉都说的很模糊. 下面说出我自己的理解. this表示的是当前对象,下面以例子来说明 <!DOCTYPE html> <html ...
- oracle AWR性能监控报告生成方法
目前相当一部分公司会用到oracle,在做性能测试的时候,对数据库的监控很重要,那么这里先介绍下如何生成oracle自带的awr监控报告,而具体报告的内容分析会放在后续的博客中 oracle性能分析入 ...
- UIView的属性
.alpha 设置视图的透明度.默认为1. // 完全透明 view.alpha = ; // 不透明 view.alpha = ; .clipsToBounds // 默认是NO,当设置为yes时, ...
- [原创]JS实现数据筛选(each)
做列表的时候,有时候需要按照某些条件进行查询,如班级,分组之类.但是又不想在重新从服务器获取数据,可以进行隐藏
- routeProvider路由的使用
先创建一个主程序文件index.html,内容如下: <!DOCTYPE html> <html ng-app="myApp"> <head> ...
- redis集群安装部署
(要让集群正常工作至少需要3个主节点,在这里我们要创建6个redis节点,其中三个为主节点,三个为从节点,对应的redis节点的ip和端口对应关系如下) 192.168.1.160:7000 192. ...
- Python 基础之基本数据类型
首先,Python中的变量不需要声明.每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建.在Python中,变量就是变量,它没有类型,我们所说的"类型"是变量所指的内存中对象 ...
- TCP流量控制和拥塞控制
TCP的流量控制 所谓的流量控制就是让发送方的发送速率不要太快,让接收方来得及接受.利用滑动窗口机制可以很方便的在TCP连接上实现对发送方的流量控制.TCP的窗口单位是字节,不是报文段,发送 ...