遇见遇见PPL::C++的并行和异步的并行和异步
并行计算正弦值
假设我们有一个数组,里面包含一组随机生成的浮点数,现在要计算每个浮点数对应的正弦值,如果你看过我的 《遇见C++
Lambda》,你可能会想到用for_each函数,如代码1所示。为了可以把数组里的浮点数替换成对应的正弦值,我们需要把
Lambda的参数声明为引用,如果你想保留那些浮点数,可以创建一个新的数组存放计算结果。
代码 1
值得提醒的是,这里使用begin和end两个函数分别获取数组的起止位置,这是C++ 11的推荐写法。此前,我们使用STL容器
的begin和end两个成员函数分别获取起止位置,但这种做法无法覆盖C风格数组;如今,C++ 11通过begin和end两个函数把
获取C风格数组和STL容器的起止位置的写法统一起来,不难想象,遵循新的写法可以提高代码的一致性。
STL提供的for_each函数是串行执行的,如果你想充分利用多核的优势,可以考虑换用PPL(Parallel Patterns Library)提供
的parallel_for_each函数,整个改造过程只需三步:
1.#include <ppl.h>
2.using namespace concurrency;
3.把for_each改为parallel_for_each,如代码2所示
代码 2
需要说明的是,如果你在Visual C++ 2010上使用PPL,你需要引用Concurrency命名空间(首字母大写),这里引用的
concurrency命名空间(全小写)是Visual C++ 2012的PPL为了和其他常见的全小写命名空间(如stl)保持一致而创建的命名
空间别名。
如果你不想影响那些浮点数,可以创建一个新的数组,然后通过parallel_for函数把计算结果对应地存到新的数组里,如代码3
所示。这里选择parallel_for函数主要是为了借助索引管理两个数组的元素的对应关系,如果你要在多个数组之间周旋,比如
说,你要为A、B、C和D四个集合实现对应元素的 (A + B) / (C - D) 操作,那么使用parallel_for函数就会非常直观。
代码 3
对于我们这里的简单需求,如果你不想自己管理元素的对应关系,可以考虑parallel_transform函数,如代码4所示。
parallel_transform函数的前两个参数指定输入容器的起止位置,第三个参数指定输出容器的开始位置,前两个参数指向的位置
之间的元素个数必须小于或等于第三个参数指向的位置和输出容器的结束位置之间的元素个数,否则将会出错。
代码 4