《C++ AMP:用Visual C++加速大规模并行计算》——3.6 parallel_for_each

简介:

本节书摘来自异步社区出版社《C++ AMP:用Visual C++加速大规模并行计算》一书中的第3章,第3.6节,作者: 【美】Kate Gregory , Ade Miller,更多章节内容可以访问云栖社区“异步社区”公众号查看。

3.6 parallel_for_each

C++ AMP:用Visual C++加速大规模并行计算
parallel_for_each函数是C++ AMP的核心,也是并行操作发生的地方。我们可以构造数组然后给它赋值,也可以构造array_view,包装std::vector等CPU密集型数据结构中的数据。之后可以使用parallel_for_each遍历数组中的每个元素,或者使用array_view,或者访问部分数据。parallel_for_each操作extent对象,extent控制着执行线程的数量。

注意事项:
parallel_for_each的变体可以操作分组extent,稍微有点儿不同。第4章和第5章会讨论parallel_for_each的变体。
下面是第1章中出现过的程序示例:

#include <amp.h>
using namespace concurrency;

void AddArrays(int n, const int* const pA, const int* const pB, int* const pC)
{
   array_view<int,1> a(n, pA);
   array_view<int,1> b(n, pB);
   array_view<int,1> c(n, pC);
   parallel_for_each(c.extent, [=](index<1> idx) restrict(amp)
   {
     c[idx] = a[idx] + b[idx];
   });
}```
上述代码对每一个原始指针(假定是C风格的数组)都使用了`array_view`,这些原始指针指向待增加的一维矩阵。每一个`array_view`都是一维的,范围为n,里面存的是整数。`parallel_for_each`的第一个参数是范围`c,array_view`存的是结果。在这个增加一维矩阵的案例中,大小(extent各维的乘积)和这三个数组视图是相同的,但在许多其他算法中,需要考虑如何挑选合适的范围值来执行线程。第二个参数是实际执行计算的`lambda`函数。在这个例子里,`lambda`是按值传入参数的。只有数组可以按引用传值(而且也只能按引用传值),其他所有类型,包括`array_view`实例,都是按值传参的。

当数组传入`parallel_for_each`时,会返回与该数组相关的`accelerator_view`(可能是默认加速器上的默认视图)。如果什么也确定不了(例如,只有`array_view`的实例传入lambda表达式),那么不管运行系统上有什么加速器,`parallel_for_each`都会在默认加速器上运行。(如果要指定运行加速器,可以选择使用以`accelerator_view`作为参数的`parallel_for_each`重载函数。)lambda表达式可以使用新引入的restrict关键字修饰,`restrict`指示编译器要保证没有什么内容不适合在加速器上运行。实际限制我们后面马上会讲到。如果你碰巧写过一个函子(`functor`),或者计算要重复在代码多处执行,就可以用函子来代替`lambda`。但是,在这些例子里,lambda是一种自然选择,代码的可读性会因为`lambda`的存在而变得更好。第12章里给出了一个使用`parallel_`
`for_each的函子的例子。

加速器针对范围内的每个元素都会启动一个线程。在上述代码示例中,c是一维`array_view`,范围取值是n,因此加速器上会启动n个线程,每个线程都会计算c的一个元素。如果c的范围是`(2,3,4`),那么加速器上运行的就是`24(2×3×4)`个线程。当然,把这么小的网格转移至加速器,根本不会意识到有什么性能提升,因为来回复制数据的成本时间已然超过了节省下来的时间。如果问题空间的计算量上升到百万级,例如范围取值为`(200,200,200`)的三维网格,而且计算也不只是把内部元素加进来这么简单,那么我们很可能就能看到巨大的性能提升。`parallel_for_each`要把正确答案计算出来,线程之间就必须得是相互独立的。执行顺序是没有保证的,例如,不可能让某个线程一直等待,直到某个其他线程计算出数值,或者线程之间进行通信。

各线程要执行的lambda或函子(`functor`)等“内核函数”有以下三个特征。

返回值类型是void。不管做的是何种计算,都应该在一个或多个数组元素或数组视图中保存。
在不分组(默认)的情况下,只有一个索引(范围的维度)。该索引的作用是确定计算的输入值,以及在哪里保存计算结果。
要使用`restrict(amp)`或`restrict(amp, cpu)`标记。
仅调用在代码生成时显式使用`restrict(amp)`或`restrict(amp, cpu)`标记的函数。这种函数的实现会在同样的`.cpp`文件里,或者是在该.cpp文件所包含的头文件的内联函数中,或者如果打开了链接时代码生成开关(`link time code generation,/ltcg`),也可能会位于链入的一个.cpp文件中。从独立执行文件中导入的函数,或者从`.lib`以及`.obj`导入的函数(没有使用`/ltcg`开关),在代码生成时是不可见的。当然,同样的限制规则也适用于从内核函数中被调用的函数。编译器必须将整个调用图内联进来才行。
参数不能是按引用传值的(除了数组实例以外)。按值传入是可以的。
传入加速器的参数类型要兼容,下节会讨论这一点。
注意事项:
在一些实际应用里,有些代码可能既想用来作`parallel_for_each`的内核,又想用于其他意图。面对这种场景,你可能需要略微放松`C++ AMP`官方文档中列举出来的那些条件规则。例如,允许函数有返回值,但`parallel_for_each`会忽视它。函数的参数除了可以是索引以外,还可以是有默认值的可选参数。如果你现在写的核函数只是要配合`parallel_for_each`使用,一般刚开始用C++ AMP的时候干的也就这点事儿,不掌握这些技术手法也没有什么问题。
相关文章
|
21天前
|
存储 C++
【C++】Visual Studio C++ 配置并使用gtest(不好用你捶我)
【C++】Visual Studio C++ 配置并使用gtest(不好用你捶我)
|
29天前
|
算法 IDE Java
【软件设计师备考 专题 】面向对象程序设计语言:C++、Java、Visual Basic和Visual C++
【软件设计师备考 专题 】面向对象程序设计语言:C++、Java、Visual Basic和Visual C++
41 0
|
29天前
|
Java API 开发工具
【软件设计师备考 专题 】C、C++、Java、Visual Basic、Visual C++等语言的基础知识和应用(三)
【软件设计师备考 专题 】C、C++、Java、Visual Basic、Visual C++等语言的基础知识和应用
30 0
|
29天前
|
Java 数据处理 数据库
【软件设计师备考 专题 】C、C++、Java、Visual Basic、Visual C++等语言的基础知识和应用(二)
【软件设计师备考 专题 】C、C++、Java、Visual Basic、Visual C++等语言的基础知识和应用
34 0
|
29天前
|
存储 算法 Java
【软件设计师备考 专题 】C、C++、Java、Visual Basic、Visual C++等语言的基础知识和应用(一)
【软件设计师备考 专题 】C、C++、Java、Visual Basic、Visual C++等语言的基础知识和应用
34 0
|
1月前
|
存储 C++ Python
C++版本netCDF在Visual Studio中的部署
【2月更文挑战第20天】本文介绍在Windows电脑的Visual Studio软件中,配置C++语言最新版netCDF库的方法~
C++版本netCDF在Visual Studio中的部署
|
2月前
|
编译器 C++
Visual Studio 2022中创建的C++项目无法使用万能头<bits/stdc++.h>解决方案
Visual Studio 2022中创建的C++项目无法使用万能头<bits/stdc++.h>解决方案
47 0
Visual Studio 2022中创建的C++项目无法使用万能头<bits/stdc++.h>解决方案
|
4月前
|
定位技术 C++
Visual Studio复制、拷贝C++项目与第三方库配置信息到新的项目中
Visual Studio复制、拷贝C++项目与第三方库配置信息到新的项目中
|
4月前
|
C++ 计算机视觉
Visual Studio新项目快速配置已有项目中编译好的C++第三方库的方法
Visual Studio新项目快速配置已有项目中编译好的C++第三方库的方法
|
4月前
|
定位技术 计算机视觉 C++
C++计算机视觉库OpenCV在Visual Studio 2022的配置方法
C++计算机视觉库OpenCV在Visual Studio 2022的配置方法

热门文章

最新文章