自 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类创建并行任务的更多相关文章

  1. .NET并行编程1 - 并行模式

    设计模式——.net并行编程,清华大学出版的中译本. 相关资源地址主页面: http://parallelpatterns.codeplex.com/ 代码下载: http://parallelpat ...

  2. 有助于提高你的 Web 开发技能的7个模式库

    正如语言风格指南一样,模式库有两个主要用途.首先,是它们提供了一组编码或设计标准,Web 开发团队可以在整个网站中应用,有助于保持一致的编码实践和外观:其次,对于要学习网页设计最佳实践来说是宝贵的财富 ...

  3. Java多线程--并行模式与算法

    Java多线程--并行模式与算法 单例模式 虽然单例模式和并行没有直接关系,但是我们经常会在多线程中使用到单例.单例的好处有: 对于频繁使用的对象可以省去new操作花费的时间: new操作的减少,随之 ...

  4. 并行模式之Guarded Suspension模式

    并行模式之Guarded Suspension模式 一).Guarded Suspension: 保护暂存模式 应用场景:当多个客户进程去请求服务进程时,客户进程的请求速度比服务进程处里请求的速度快, ...

  5. 并行模式之Master-Worker模式

    并行模式之Master-Worker模式 一).Master-Worker模式 作用: 将一个大任务分解成若干个小任务,分发给多个子线程执行. 注: 将大任务分解成小任务,小任务的实现逻辑要相同. 二 ...

  6. oracle并行模式

    参考链接:oracle并行模式(Parallel),深入理解Oracle的并行操作(原创),oracle使用并行踩过的坑 1. 语法(这个可以加到insert.delete.update.select ...

  7. 【C/C++开发】C++静态库与动态库以及在Linux和Windows上的创建使用

    原文出处: 吴秦的博客    这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学 ...

  8. .NET 4 并行(多核)编程系列之三 从Task的取消

    原文:.NET 4 并行(多核)编程系列之三 从Task的取消 .NET 4 并行(多核)编程系列之三 从Task的取消 前言:因为Task是.NET 4并行编程最为核心的一个类,也我们在是在并行编程 ...

  9. SSIS从理论到实战,再到应用(1)----创建自己的第一个包

    原文:SSIS从理论到实战,再到应用(1)----创建自己的第一个包 其实,如果你使用sql2008的导出导入工具的时候,你就已经在使用包了. 目标:使用sql2008 导入导出工具,导入excel数 ...

随机推荐

  1. Vim安装YouCompletMe插件。

    1.Centos7.0自带含有支持python2.x的vim.(:version 后看python+则支持,python-则不支持)若不支持,卸载vim后源码编译安装. yum install pyt ...

  2. centos系统修改网络配置注意事项

    这也是无意之中发现的,我在做一个远程修改工控机网络配置的程序, 网络配置参数/etc/sysconfig/network-scripts/ifcfg-enp1s0下面,当然名字可能不一样ifcfg-e ...

  3. hadoop集群间的hdfs文件拷贝

    1.背景 部门有个需求,在网络互通的情况下,把现有的hadoop集群(未做Kerberos认证,集群名为:bd-stg-hadoop)的一些hdfs文件拷贝到新的hadoop集群(做了Kerberos ...

  4. Spring 日期时间处理

    1 Spring自身的支持 1.1 factory-bean <bean id="dateFormat" class="java.text.SimpleDateFo ...

  5. 远程登录aws

    AWS的EC2服务器是用密钥来认证的,在创建instance时,会提示,创建一个key pair,同时会提示下载一个xxx.pem的密钥文件到本地硬盘.下面是通过SecureCRT连接到EC2的操作步 ...

  6. Quartz.net 定时任务之简单任务

    一.概述 1.quartz.net 是一款从java quartz 上延伸出来的定时任务框架. 2.我在网上看到很多大神写过关于quartz.net 的博客.文章等,在这些博客文章里也学会了很多关于q ...

  7. 开涛spring3(4.3) - 资源 之 4.3 访问Resource

    4.3.1  ResourceLoader接口 ResourceLoader接口用于返回Resource对象:其实现可以看作是一个生产Resource的工厂类. public interface Re ...

  8. 【原创】iOS图片预览(支持缩放和移动)

    1.传入图片 PreViewController.h: #import <UIKit/UIKit.h> @interface PreViewController : UIViewContr ...

  9. Github+Hexo,搭建专属网站

    前言 记得从大二开始,就一直想搭个专属网站,当时使劲抠页面[前端页面是从QQ空间抠的,现在想抠估计没这么容易了],写代码,忙活半天才把程序弄好. 可惜最终项目还是没上线,因为当时有两问题绕不开 需要购 ...

  10. Java 开发中如何正确踩坑

    为什么说一个好的员工能顶 100 个普通员工 我们的做法是,要用最好的人.我一直都认为研发本身是很有创造性的,如果人不放松,或不够聪明,都很难做得好.你要找到最好的人,一个好的工程师不是顶10个,是顶 ...