Visual C++ 2013 的 STL 平行化函数库
之前在《C++14 C++编程爱好者看过来》一文中有提过了,在 C++14 这个尚未定案的 C++ 新标准里、又针对了 C++ 的核心语言、以及标准函示库(STL)做出了若干的改进。其中,Heresy 觉得相当重要的一部分,就是让平行化程序开发更简单的 STL 新函示库、Parallel STL 了!
而之前在《Modern C++: What you need to know》一文也有提过,微软在 Build 2014 上曾经预告过,将会放出根据《Working Draft, Technical Specification for C++ Extensions for Parallelism》实作的 Parallel STL 雏型版本;而现在,微软终于把他放在 CodePlex 上了!
官方的介绍,是《Parallel STL – Democratizing Parallelism in C++》这篇文章,专案的网址则是:https://parallelstl.codeplex.com/
要下载最新版本的话,基本上就是到‘Source Code’里面、点击右上方的‘Download’就可以把整个打包成 ZIP 下载了(链结);而如果有需要的话,也可以用 Git 把整个 clone 下来。
简介
这套 Parallel STL 基本上算是 STL algorithm(参考)的延伸,所以它的内容基本上都和 STL algorithm 一样、主要是针对 STL container 做处理;差别只是在于现行的 STL algorithm 提供的含式都是以单一执行序来执行的,而 Parallel STL 所提供的,则都是平行化处理的版本、理论上可以更好地发挥多核心处理器的效能!
而和 OpenMP 相比,Parallel STL 除了也可以透过 for_each() 把循环平行化外,主要其实还是他针对一些常见的演算法,提供了平行化的实作;像是 sort()、count()、reduce()、transform()、search() 等等,在有需要的时候,都可以直接拿来使用,而不需要自己重新实作,算是相当方便的!
另外,虽然目前他还是只有使用多核心 CPU 来做平行化,但是由于他是定义出一个标准程序介面、然后让大家自己去实作,所以应该也可以期待、以后可以透过同样的函数介面,来完成 GPU 的平行化吧~
函数库准备
由于这个 Parallel STL 基本上还是一个独立的函数库,所以如果希望能在自己的专案里使用的话,需要先把它建置成 lib 和 dll 才行。
在打开 ParallelSTL.sln 这个方案后,里面可以找到‘ParallelSTLDesktop’ 这个专案,他基本上就是 Parallel STL 给 native C++ 用的函数库了~
在建置好这个专案后,以 x86 的 release 版来说,可以在‘release’文件夹下,找到建置出来‘ParallelSTL.lib’和‘ParallelSTL.dll’档;至于其他的建置环境(x64、debug 等),所建置出来的文件则是会在其他对应的目录下,应该也可以简单地找到。
再加上‘include’目录下的 header 档,这样就可以在其他专案里面使用 Parallel STL 了。而之后如果所使用的开发环境有直接支援 Parallel STL 的话,就不需要做这些步骤,而可以直接使用了。
程序的撰写
如果要使用 Parallel STL 的话,程序要做那些修改呢?其实相当简单!首先,要注意的是:Parallel STL 因为目前还没定案,还被视为 experimental、实验性的功能,所以不管是 header 还是 namespace,都还有 experimental 的字样;这个等正式定案之后,应该是会被拿掉的。
以目前还说,要使用 Parallel STL,基本上就是要 include ‘experimental/algorthim’这个文件;而之后,所有的相关函数,都会在‘std::experimental::parallel’这个 namespace 下。
如果以要针对一个 STL 的 container v 做排序来说,使用标准 STL 的写法,会是类似下面这样:
- using namespace std;
- sort(v.begin(), v.end());
而要改用平行化的版本的话,则只需要改成:
- using namespace std::experimental::parallel;
- sort(par, v.begin(), v.end());
这样就可以了!
可以看到,除了 namespace 从 std 变成 std::experimental::parallel 外,程序码的修改,就只有 sort() 这个函数多了一个参数 par,要修改的地方相当地少~
而这边的 par 是用来告诉 Parallel STL 要怎么去执行这个函数用的,在现阶段的规范里面,有三种方法:
seq:sequential execute、序列化执行、不要平行化
par:parallel execute、平行化执行
vec:vector execute、向量化执行(维基百科)
透过这个参数,就可以在程序里面简单地控制是否要平行化、或是要以向量化的方式来执行了。而 Parallel STL 提供的其他函数,也都是类似的状况,只需要在前面多加这个参数就可以了~
如果是要把循环给平行化的化,则是可以使用 for_each() 这个函数,来扫过整个 container;下面就是一个简单的例子:
- using namespace std::experimental::parallel;
- for_each(par, vData.begin(), vData.end(), [](int& iVal){
- iVal = iVal* iVal;
- });
在这个例子里面,就是透过 for_each() 来对 vData 这个 vector 里面每一项作平方的计算。这样的写法,如果用 OpenMP 的化,则会是:
- #pragma omp parallel for
- for (int i = 0; i < vData.size(); ++i)
- vData[i] = vData[i] * vData[i];
两者哪种好用?这就见仁见智了~
简单的效能测试
以官方提供的‘Sort_Sample’这个效能测试用的范例程序来说,在 Heresy 的 Intel Core i7-3612QM 这颗四核心、八执行序的电脑上,其结果摘录如下:
Testing sort of 100000 ints:
serial: 0.000 seconds
parallel STL: 0.000 seconds
PPL: 0.000 seconds
Testing sort of 1000000 ints:
serial: 0.031 seconds
parallel STL: 0.000 seconds
PPL: 0.000 seconds
Testing sort of 10000000 ints:
serial: 0.234 seconds
parallel STL: 0.078 seconds
PPL: 0.062 seconds
Testing sort of 50000000 ints:
serial: 1.156 seconds
parallel STL: 0.328 seconds
PPL: 0.328 seconds
Testing sort of 100000000 ints:
serial: 2.437 seconds
parallel STL: 0.671 seconds
PPL: 0.656 seconds
可以看到,如果效能可以量测的话(>=10000000),用 Parallel STL 进行排序所需的时间,大概会是标准、没有平行化版本的 1/3 – 1/4~这个效能的进步相当多了!
补充:
这个函数库由于采用新的 C++ 语法来做开发,所以必须使用 Visual Studio 2013 以后的版本才能使用,如果使用 Visual Studio 2012 则会有编译错误。
Parallel STL 在 debug 模式下的效能可能会比没有平行化更差,如果要做效能测试,请记得使用 release 版。
微软之前其实也有提供一个平行化的函数库 Parallel Patterns Library(PPL)可以使用(参考),不过那是 Visual Studio 专用的;而现在的 Parallel STL 则是未来的 C++ STL 标准函数库,可以在不同的开发环境使用。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
