当前位置: 首页 > 编程日记 > 正文

Concurrency Runtime in Visual C++ 2010

PDC 2010 Hejlsberg的演讲中我们看到了VB.NET、C#新的简化异步编程的方式(可以下载新的Async CTP体验)。之前的TPL(Task Parallel Library)简化了并行编程。工业语言的飞速发展大大改进、简化了开发人员的编程方式。不仅是微软平台的托管语言,非托管语言也始终保持着一定程度的进化,我想通过两三篇文章来讲述Visual C++ 2010并行编程相关的内容。在介绍Visual C++ 2010的ppl之前,先简单介绍两个比较重要的新语法特性:

1、auto关键字

Visual C++ 2010中的auto关键字不再是以前简单的自动变量的概念,它被用于简化变量原型编译时的自动化推导。

1 vector numVec;
2 
3 for (vector::const_iterator iter = numVec.begin(); iter != numVec.end(); ++iter) {
4 
5 }

vector的遍历器写法稍微有些长了,代码过于烦琐。现在使用auto关键字编写:

1 vector numVec;
2 
3 for (auto iter = numVec.begin(); iter != numVec.end(); ++iter) {
4 
5 }

auto关键字的用法和C# 3.0新增的var关键字相同,用于简化那些编译时可以确定类型的声明。

1 Int32[] numArray = { 1, 2, 3, 4, 5 };
2 IOrderedEnumerable iter = numArray.Where(p => p > 0).OrderBy(p => p);
3 var iter2 = iter;

2、Lambda表达式

微软平台的托管语言都支持匿名函数,Lambda是为实现匿名函数提供了函数式的语法。

1 Int32[] numArray = { 1, 2, 3, 4, 5 };
2 var iter = numArray.Where(p => p > 0).Max();

旧有的Visual C++对于编写STL sort函数自定义排序需要这么编写:

1 bool less2(const int& lhs, const int& rhs) {
2     return lhs < rhs;
3 }
4 
5 vector numVec;
6 
7 sort(numVec.begin(), numVec.end(), less2);
8 sort(numVec.begin(), numVec.end(), less<int>());

Visual C++ 2010:

1 vector numVec;
2 
3 sort(numVec.begin(), numVec.end(), [&](int& lhs, int& rhs) { return lhs < rhs; });

对于一些不超过4、5行以上的代码,我个人更愿意使用匿名函数。Visual C++ 2010的ppl的定义被包含在ppl.h中。下面先看一段简单的代码:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int sum = 0;
 6 
 7 for (int i = 1; i < 101; ++i)
 8     sum += i;
 9 
10 wcout << “Result=” << sum << endl;

这组操作如果基于ppl该如何编写:

 1 #include <iostream>
 2 #include <ppl.h>
 3 
 4 using namespace std;
 5 using namespace Concurrency;
 6 
 7 int sum = 0;
 8 
 9 parallel_for(1, 101, 1, [&](int n) {
10     sum += n;
11 });
12 
13 wcout << “Result=” << sum << endl;

ppl提供了parallel_for,它的处理方式和for循环语句一样,下面是parallel_for在ppl.h中的定义:

1 template
2 void parallel_for(_Index_type _First, _Index_type _Last, _Index_type _Step, const _Function& _Func)

_First为起始索引、_Last为结束索引、_Step为步长、_Func为被调用函数指针。我以前的文章提到过Visual C++ 2008开始就提供了for each的支持,对于遍历vector之类的STL容器可以用for each实现(Visual C++的for each在for和each之间是有空格的,和Visual C#不同):

1 vector numVec;
2 
3 numVec.push_back(1);
4 
5 for each (int i in numVec) {
6     wcout << i << endl;
7 }

同样的ppl也提供了for each版本的并行函数parallel_for_each:

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <ppl.h>
 4 
 5 using namespace std;
 6 using namespace Concurrency;
 7 
 8 int sum = 0;
 9 const int NUMBER_ARRAY_SIZE = 10;
10 int numArray[NUMBER_ARRAY_SIZE];
11 
12 generate(numArray, numArray + NUMBER_ARRAY_SIZE, rand);
13 
14 parallel_for_each(numArray, numArray + NUMBER_ARRAY_SIZE, [&](int n) {
15     sum += n;
16 });
17 
18 wcout << “Result=” << sum << endl;

上面提到的parallel_for和parallel_for_each都是基于容器的遍历,ppl提供了parallel_invoke用于并行执行多个函数体。

 1 #include “stdafx.h”
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <ppl.h>
 5 
 6 using namespace std;
 7 using namespace Concurrency;
 8 
 9 void Func1() {
10     int sum = 0;
11     const int NUMBER_ARRAY_SIZE = 10;
12     int numArray[NUMBER_ARRAY_SIZE];
13 
14     generate(numArray, numArray + NUMBER_ARRAY_SIZE, rand);
15 
16     for each (int n in numArray) {
17         sum += n;
18     }
19 
20     wcout << “Result=” << sum << endl;
21 }
22 
23 parallel_invoke(&Func1, &Func1);

parallel_invoke最多支持10个function的函数重载。超过10以上的function完全可以用parallel_for和parallel_for_each来实现调用。

ppl提供了一些容器类型和对象用于线程安全的操作。先简单介绍两个容器类型concurrent_vector和concurrent_queue。这两个容器的使用方式和普通的STL的vector和queue相同,但有一个非常重要的区别在于它们的存储空间不是连续的,比如原来你操作vector时可以通过指针加减操作进行数据访问:

1 vector<int> vecArray;
2 
3 int val = *(&vecArray[0] + 5);

但是对于concurrent_vector、concurrent_queue使用这种访问方式它的结果是未定义的,可能访问成功,可能是已经分配使用的内存空间或者访问违例。

1、concurrent_vector(使用方式和STL的vector相同)

 1 #include <iostream>
 2 #include <ppl.h>
 3 #include <concurrent_vector.h>
 4 
 5 concurrent_vector<int> vecArray;
 6 
 7 parallel_invoke(
 8 [&vecArray] {
 9     for (int i = 0; i < 50; ++i)
10         vecArray.push_back(rand());
11 },
12 [&vecArray] {
13     for (int i = 0; i < 100; ++i)
14         vecArray.push_back(rand());
15 });
16 
17 for each (int n in vecArray)
18     wcout << n << endl;

2、concurrent_queue(STL的queue在访问元素时调用pop,而concurrent_queue则是try_pop)

 1 #include <iostream>
 2 #include <ppl.h>
 3 #include <concurrent_queue.h>
 4 
 5 concurrent_queue<int> queueArray;
 6 
 7 parallel_invoke(
 8 [&queueArray] {
 9     for (int i = 0; i < 50; ++i)
10         queueArray.push(rand());
11 },
12 [&queueArray] {
13     for (int i = 0; i < 100; ++i)
14         queueArray.push(rand());
15 });
16 
17 int val = 0;
18 
19 while (!queueArray.empty() && queueArray.try_pop(val))
20     wcout << val << endl;

ppl提供了一种可以合并操作的类型用于将不同线程间的本地存储值进行一定的操作,以往我们编写一个多线程或者并行操作计算总和的时候需要通过各种手段来确保操作值的更新,看一个最简单的例子:

1 volatile long sum2 = 0;
2 
3 parallel_for(1, 101, [&sum2](int n) {
4     InterlockedExchangeAdd(&sum2, n);
5 });
6 
7 wcout << sum2 << endl;

再来看使用ppl新增的combinable类型完成同样的操作:

 1 #include <iostream>
 2 #include <ppl.h>
 3 
 4 combinable sum3;
 5 
 6 parallel_for(1, 101, [&sum3](int n) {
 7     int& local = sum3.local();
 8 
 9     local += n;
10 });
11 
12 wcout << sum3.combine(plus()) << endl;

combinable的combine是一个模板函数用来定义函数指针,所以完全可以通过简单的lambda表达式定义自己的操作。默认提供了诸如:plus、multiplies、divides、minus操作。上面的例子最后一步的combine也可以这样写:

wcout << sum3.combine([&](int n1, int n2) { return n1 + n2; }) << endl;

转载于:https://www.cnblogs.com/junchu25/archive/2012/08/11/2633505.html

相关文章:

关于安卓你不知道的6件事

安卓第一次亮相是出如今2008年公布的HTC Dream手机上&#xff0c;到如今为止它已经6岁了。或许没有人想过在2010年底它就成为了智能手机平台率先的操作系统。这当然要感谢谷歌的努力和强大的財力支持。尽管眼下安卓系统是世界上最流行的移动操作系统&#xff0c;可是关于它的非…

vmware的三种网络模式讲解

vmware有三种网络设置模式&#xff0c;分别是Bridged(桥接),NAT(网络地址转换)&#xff0c;Host-only(私有网络共享主机) 1.Bridged(桥接) 桥接模式默认使用的是&#xff1a;VMnet0 什么是桥接模式&#xff1f;桥接模式就是把主机网卡和虚拟机虚拟的网卡利用虚拟网桥进行通信。…

当前路径_[JSP] 07 JSP 路径问题

首先先明确一下下列URL的假设一个URL是这样的losthost:8080/myservlet/path服务器根路径:losthost:8080/项目根路径:losthost:8080/myservlet/明确了服务器根路径和项目根路径之后,我们就可以开始学习后面的知识了servlet路径问题请求转发和重定向的相对路径写法总结:Servlet重…

CPU时间戳获取

inline long long timt(){long long p; int&a*(((int*)&p)1);__asm__ __volatile__("rdtsc":"a"(p),"d"(a));return p; } 因为在64位CPU上rdtsc出来的结果仍然是在%eax和%edx,而%rax却不是由%eax和%edx拼起来的(反正我试了它没用...也许…

NYOJ 366 D的小L

地址&#xff1a;http://acm.nyist.net/JudgeOnline/problem.php?pid366 方法&#xff1b;用next_permutation&#xff08;pɝmjʊteʃə&#xff09;来求解&#xff0c;递归调用代码 1 #include<stdio.h>2 #include<algorithm>3 using namespace std;4 int main(…

MySQL 语句整理 2019-5-3

MySQL 语句整理 在整理完Oracle的一些常见用语句后,由于MySQL的语法跟Oracle略有不同,随跟PN的MySQL视频进行了间接整理. 查询薪水大于1800, 并且部门编号为20或30的员工sql select deptno,ename,sal from emp where sal > 1800 and (deptno 20 or deptno 30); and 优先级…

联想e580没有声音_现在你可以购买通过 Linux 认证的联想 ThinkPad 和 ThinkStation

曾经有一段时间&#xff0c;ThinkPad 是 Linux 用户的首选系统。但那是在 ThinkPad 还是 IBM 的产品的时候。来源&#xff1a;https://linux.cn/article-12283-1.html作者&#xff1a;Abhishek Prakash译者&#xff1a;Xingyu.Wang曾经有一段时间&#xff0c; ThinkPad 是 Linu…

linux平台下防火墙iptables原理(转)

原文地址&#xff1a;http://www.cnblogs.com/ggjucheng/archive/2012/08/19/2646466.html iptables简介 netfilter/iptables&#xff08;简称为iptables&#xff09;组成Linux平台下的包过滤防火墙&#xff0c;与大多数的Linux软件一样&#xff0c;这个包过滤防火墙是免费的&a…

SQL语法大全

SQL语句大全 --语 句 功 能--数据操作SELECT --从数据库表中检索数据行和列INSERT --向数据库表添加新数据行DELETE --从数据库表中删除数据行UPDATE --更新数据库表中的数据--数据定义CREATE TABLE --创建一个数据库表DROP TABLE --从数据库中删除表ALTER TABLE --修改数据库表…

Node.js的url模块简介

什么是URL URL是Uniform Location Resource的缩写&#xff0c;翻译为“统一资源定位符”&#xff0c;也就是描述资源位置的固定表示方法。被URL描述的资源可以位于互联网上&#xff0c;也可以位于本地。 URL的组成结构 基本URL包含模式&#xff08;或者成为协议&#xff09;&am…

python游戏结束显示分数代码_当游戏循环在Python中运行时,多线程来显示游戏分数?...

我想根据比赛时间的推移得分。为此&#xff0c;我想让两个循环同时运行。游戏循环和得分循环&#xff0c;每1.5秒加1。当我运行程序时&#xff0c;分数不会出现。我是否正确使用多线程&#xff1f;这是最好的办法吗&#xff1f;为了简单起见&#xff0c;我只发布了相关代码。谢…

NOIP2015解题报告 By ljt12138

Day1t1 幻方 练过的一道题&#xff0c;简单模拟&#xff0c;用二维数组存储&#xff0c;ij两个游标记录横纵坐标&#xff0c;利用题目条件改变坐标直到填入n个数即可。复杂度O(n^2) AC Day2t2 图的最小环 首先抽象出图论模型。每个人对应点&#xff0c;传输对应边。因为自己…

设计模式笔记——Adapter

适配器模式Adapter 将一个类的接口转换成用户希望的另外一个接口。适配器模式主要应用于希望复用一些现存的类&#xff0c;但是接口又与复用的环境要求不一样的情况。 package adapter.pattern; /*** * author Real H LI**/ public class Existed {public void OldRequest(){Sy…

iOS12-crash错误-reason: 'UITableView failed to obtain a cell from its dataSource'

错误原因&#xff1a; cellForRowAtIndexPath函数返回了nil override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {let cell tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: in…

with as python_python - with as的用法

摘自&#xff1a;http://www.cnblogs.com/DswCnblog/p/6126588.htmlWith 是什么&#xff1f;有一些任务可能事先需要设置&#xff0c;事后做清理工作。对于这种场景&#xff0c;Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理&#xff0c;你需要获取…

wcf系列学习5天速成——第四天 wcf之分布式架构(转载)

今天是wcf系列的第四天&#xff0c;也该出手压轴戏了。嗯&#xff0c;现在的大型架构&#xff0c;都是神马的&#xff0c; nginx鸡群&#xff0c;iis鸡群&#xff0c;wcf鸡群&#xff0c;DB鸡群&#xff0c;由一个人作战变成了群殴....... 今天我就分享下wcf鸡群&#xff0c;高…

检测jQuery.js是否已加载的判断代码

转载自http://www.jb51.net/article/27185.htm 测类、方法、变量或属性是否已存在&#xff0c;这是Javascript编程基础知识。在这里我们就是要检测jQuery()或$()函数是否存在 当然&#xff0c;该方法不局限于jQuery的检测&#xff0c;对与任何Javascript变量或函数都是通用的。…

Java中常见的锁简述

在Java的应用中&#xff0c;或多或少的都会接触到一些锁&#xff0c;那么问题就来了&#xff0c;在Java中&#xff0c;常见的锁有哪些&#xff0c;都有什么样的作用&#xff1f;&#xff1f; 这里给大家简单的简述一下这些学常见的锁。 本文件所涉及到的锁&#xff1a; 1.公平锁…

加了好友怎么还掉血_微信聊天窗口出现风险提醒,无法添加好友解决办法

再更&#xff0c;你想马上解封&#xff0c;你得有朋友。没有朋友&#xff0c;你就等个十天半个月&#xff01;更新一下 帖子浏览人挺多的&#xff0c;有问题可以在评论里相互交流&#xff0c;下面是原文&#xff1a;先让我说一句脏话&#xff1a;傻x微信风控系统 终于特么的聊天…

[小明爬坑系列]AssetBundle原理介绍

一.简介 Assetbundle 是Unity Pro提供提供的功能&#xff0c;它可以把多个游戏对象或者资源二进制文件封装到Assetbundle中&#xff0c;提供了封装与解包的方法使用起来很便利。 二.移动平台特点 Assetbundle是可以把预制,文件以及场景都打包到Assetbundle中去的,但是在移动平台…

Ubuntu16.04菜单栏侧边栏不显示

2019独角兽企业重金招聘Python工程师标准>>> &#xff08;&#xff11;&#xff09;只有桌面上显示一些原有的文档或图片。但打开文档或者图片后也是没有窗口菜单栏&#xff0c;这样连关闭都没法点&#xff0c;快捷&#xff21;ltF4也没有反应。而且鼠标点击拖动不了…

C 语言中的 strtok 调用小技巧

1 #include <stdio.h>2 #include <string.h>3 4 char *my_strtok(char *buf, char *delims)5 {6 static int first 1;7 if(first){ //8 first 0; // 互斥操作&#xff0c;确保后面代码仅在本次调用执行9 return strtok(buf, delims); 10…

powershell连接数据库_PowerShell 连接SQL Server 数据库

PowerShell 通过ADO.NET连接SQL Server数据库&#xff0c;并执行SQL脚本。工作中整理的一小段脚本&#xff0c;后来没有用上&#xff0c;先记录在这里&#xff1a;建立数据库连接查询返回一个DataTatble对象执行一条SQL语句通过事物执行多条SQL语句## 建立数据库连接.#function…

GDB调试进阶

GDB 调试 ------------------------------------------------------------------------------- gdb 帮助文档 help -- 查看 gdb 的命令种类 help <CmdType> -- 查看 CmdType 种类的 gdb 命令 apropos <keyWord> -- 查看关键字 keyWord 的相关命令 info <keyWord…

RubyGems 库发现了后门版本的网站开发工具 bootstrap-sass

安全研究人员在官方的 RubyGems 库发现了后门版本的网站开发工具 bootstrap-sass。该工具的下载量高达 2800 万次&#xff0c;但这并不意味着下载的所有版本都存在后门&#xff0c;受影响的版本是 v3.2.0.3&#xff0c;研究人员呼吁用户尽可能快的更新&#xff0c;认为可能有数…

读大叔深入理解javascript(2)

Module模式的应用&#xff1a; var Caculator function(eqt){var box document.getElementById(eqt);return {add:function(x,y){return xy;}} }; var a new Caculator(11); a.add(1,3); // return 4 这种方式每次都需要new 一下&#xff0c;也就是说每个实例在内存里都是一…

android 无法接收广播_别告诉我你不认识Android中广播接收者(二)

前面我们了解了什么是广播接收者与广播接收者的创建&#xff0c;这一次我们要接着继续去了解广播接收者的相关知识&#xff0c;这些知识包括广播接收者的注册、自定义广播与广播的类型。当我们学习完广播接收者之后&#xff0c;该如何才能让它起到作用呢&#xff1f;还有广播接…

jQuery中$(function(){})与(function($){})(jQuery)的区别

首先&#xff0c;这两个函数都是在页面载入后执行的函数&#xff0c;其中两者的区别在于&#xff1a; 在jQuery中$(function(){})等同于jQuery(function(){})&#xff0c;另一个写法为jQuery(document).ready(function(){ })&#xff0c;在DOM加载完成之后立即执行&#xff0c;…

UITableView注意点

在iOS应用中&#xff0c;UITableView应该是使用率最高的视图之一了。iPod、时钟、日历、备忘录、Mail、天气、照片、电话、短信、 Safari、App Store、iTunes、Game Center⋯几乎所有自带的应用中都能看到它的身影&#xff0c;可见它的重要性。然而在使用第三方应用时&#xff…

083、Prometheus架构(2019-05-05 周日)

参考https://www.cnblogs.com/CloudMan6/p/7692765.htmlPrometheus 是一个非常优秀的监控工具&#xff0c;准确的说&#xff0c;应该是监控方案。Prometheus 提供了监控数据搜集、存储、处理、可视化和告警一整套的解决方案。Prometheus 重要组件的架构如下&#xff1a;Prometh…