多线程并行程序性能分析方法综述之MKL 数学核心函数库

2.3 MKL数学核心函数库

Intel® 性能库提供了高度优化的函数,这些函数可充分利用Intel® 多核处理器,从而能够最大限度地获得应用程序的性能并减少开发时间。

Intel® 数学核心函数库(MKL)是一套经过高度优化的、线程安全的数学例程、函数,并在此基础上加入了在Linux集群环境下的ScaLAPACK(Scalable LAPACK – http://www.netlib.org/scalapack),它们专门针对计算性能要求很高的科学、工程及金融等领域的应用程序而设计。



2.3.1 MKL数学核心函数库功能与特性

此内核库的功能领域包括:

(1)线性代数 --BLAS、LAPACK

在Intel® 处理器中部署经过高度优化的基本线性代数例程(Basic Linear Algebra Subroutines,BLAS)和线性代数包(linear algebra package,LAPACK)(拥有数百个例程),它们提供的性能改善非常显著,远远超出其他替代性实现。

BLAS分为以下几个级别:

一级BLAS:矢量-矢量运算
15 个函数类型
48 个函数

二级BLAS:矩阵-矢量运算
26 个函数类型
66 个函数

三级BLAS:矩阵-矩阵运算
9 个函数类型
30 个函数

扩充BLAS:一级BLAS专用于稀疏向量运算
8 个函数类型
24 个函数

以下稀疏矩阵 BLAS 三角形矩阵解算器是采用 OpenMP 进行线程处理的。
mkl_dcsrmm - 压缩稀疏矩阵行格式的 3 级三角形矩阵解算器;
mkl_dcscmm - 压缩稀疏矩阵列格式的 3 级三角形矩阵解算器;
mkl_dcoomm - 坐标格式的 3 级三角形矩阵解算器。

(2)ScaLAPACK

ScaLapack是一个并行计算软件包,适用于分布存储的MIMD并行机。ScaLapack提供若干线性代数求解功能,具有高效、可移植、可伸缩、高可靠性的优点,利用它的求解库可以开发出基于线性代数运算的并行应用程序。

ScaLAPACK的Intel® MKL 实现提供的性能改善非常显著,远远超出标准 NETLIB 实现。

(3)PARDISO稀疏矩阵解算器

利用 PARDISO 稀疏矩阵解算器(该解算器是经巴塞尔大学许可的、易于使用、线程安全、高性能且高效利用内存的软件库)可在共享内存的多处理器上解算大型、稀疏、对称以及不对称线性方程组。Intel® MKL 还包括一个带有灵活的反向通信接口的共轭梯度迭代解算器(Conjugate Gradient iterative solver)。

9.0中实现了新的 RCI Flexible Generalized Minimal RESidual (FGMRES) 迭代解算器。

(4)离散傅立叶变换(Discrete Fourier transforms,DFTs)

采用多维 FFT 例程(1 维到最多 7 维,支持混合基数),并提供一个易于使用的先进的 C/Fortran 接口。Intel® MKL 还提供一系列 C 语言例程,这些例程模拟 FFTW 2.x 和 3.0 接口,从而与目前使用 FFTW 的用户无缝兼容。

(5)矢量数学库(Vector Math Library,VML)

可提高带有计算密集型核心数学函数(幂函数、三角函数、指数函数、双曲函数、对数函数等)的矢量实现的应用的速度。该库在9.0中新增的功能有:

VML 目前支持将单精度复数和双精度复数用于以下函数:Acos、Acosh、Asin、Asinh、Atan、Atanh、Cos、Cosh、Exp、Ln、Log10、Pow、Powx、Sin、Sinh、Sqrt、Tan、Tanh。

新的单精度和双精度最接近整数的函数:Trunc、Ceil、Floor、Round、NearbyInt、Rint。

还增加了另外三个单精度和双精度参数的函数:ErfInv、Hypot 和 Modf。

VML 函数目前已采用 OpenMP进行线程处理。

(6)矢量统计库(Vector Statistical Library,VSL)--随机数生成器

利用矢量随机数生成器加速模拟,与标量随机数生成器相比,它能够显著提升系统性能。该库在9.0中新增的功能有:

提供了快速/精确的分布生成模式。

支持根据用户定义的拟随机数生成器的参数来生成拟随机序列。



2.3.2 MKL数学核心函数库性能

新版9.0版的数学核心函数库相对于之前的版本性能有了极大的提升,具体如下:

(1)Intel® 安腾2 处理器

FFT:
单双精度,1 维实数 FFT 在 n = 2、4、8、16、32、64 和 128 时速度最多提高了 3 倍

VML:
Ln、Log10、Asin、Acos、Sinh、Cosh 函数的性能提高了 25-83%
长矢量(双精度 n>250,000 或单精度 n>500,000)的性能平均值提高了 60% 以上。这使每个元素的性能限定在小矢量性能的 20% 以内。

VSL:
高斯和多元高斯分布生成器的性能分别提高了 35% 和 15%。

(2)Intel® 酷睿2 双核处理器

BLAS:
ZDOTU、ZDOTC - 缓存数据的性能提高了 10-35%

VSL:
性能提高了大约 13%

VML:
VML 中 Div 和 Inv 函数的性能提高了 2.7 倍
Asin 和 Acos 函数的性能提高了 5 - 20%

(3)Intel® 奔腾4 与Intel® 至强处理器

BLAS:
CGEMV - 并行数据的性能提高了 30-80%

ZGEMV - Intel® 64 位架构系统上的未并行数据的性能提高了 5-35%
DTRMV - 小尺寸的性能提高了 20%
SNRM2、SCNRM2 - 缓存数据的性能最多提高了 10 倍
ZDOTU、ZDOTC - 缓存的并行数据的性能提高了10-25%,未并行数据的加速比提高了2倍

(4)其他提升

SPARSE BLAS:
压缩稀疏矩阵行格式的稀疏矩阵矢量乘法例程的性能提高了 20-50%。以下函数受到影响:mkl_dcsrgemv、mkl_dcsrsymv 和 mkl_dcsrmv。
Asin 和 Acos 函数的性能提高了 5 - 20%

FFT:
2 的幂的大小大于 17 的单双精度 1 维复数 FFT 的性能最多提高了 40%
在 64 位模式下运行的Intel® 64 位架构系统上,1 维实数的 FFT 在 n = 2、4、8、16、32 或 64 时最多提高了 3 倍

VML:
通过 OpenMP* 的自动线程处理,函数可利用多处理器系统(矢量长度为 n > 200),以及支持Intel® 超线程技术的系统(矢量长度为 n > 10000)。在双核处理器和双处理器系统上,系统性能最多提高了 90%



2.3.3 MKL数学核心函数库实验

本实验学习如何使用Intel® 数学核心函数库中的例程以及多线程能力。

(1)矩阵乘法

本实验通过分别用原始运算、DDOT、DGEMV、DGEMM编译和运行一个矩阵乘法程序,演示了原始计算、一级BLAS、二级BLAS、三级BLAS的性能特征和它们之间的差异。请按照以下实验步骤执行:

定位到文件夹code\ MKL_Overview\DGEMM,打开文件mkl_lab_solution.c,仔细查看4段不同方法实现同一矩阵乘法的代码;

检查文件Makefile中的include和library路径,修改为与本机一致;

打开开始菜单->所有程序->Intel(R) Software Development Tools->Intel(R) C++ Compiler 9.0->Build Environment for IA-32 Applications,输入:nmake,编译完成后目录下会生成一个matrix.exe文件,输入:matrix.exe运行程序,会提示输入矩阵的维数(输入的数字尽量大些,如1000),记录运行结果并观察它们的差异:
roll_your_own: ___________
DDOT: __________
DGEMV: ___________
DGEMM: ___________
MKL默认使用单线程,可以通过改变环境变量OMP_NUM_THREADS来自定义MKL使用的线程数量,输入:set OMP_NUM_THREADS=2,重新运行程序观察结果;

改变不同线程数量,记录各自的运行结果。

问题:
当自定义的线程数量超过处理器核的数量时,会发生什么现象?

(2)蒙特卡罗法计算圆周率

本实验通过使用MKL中矢量统计库(VSL)的随机数生成器来修改经典的圆周率计算法--蒙特卡罗法,在实验中会用到VSL的多线程能力。请按照以下实验步骤执行:

定位到文件夹code\ MKL_Overview\MonteCarloPi,打开文件pimonte.c。理解函数rand()实现的原理;

问题:
代码中的循环体能用多线程实现吗?
打开文件pimonte_VSL.c,观察用库函数调用替代函数rand()所产生的变化;

问题:
为什么不是1:1的直接替换rand()函数?
设置blocksize的目的是什么?
参数BRNG 和VSL_BRNG_MCG31的作用是什么?
对这个程序来说,它们是最好的选择吗?
能用多线程实现吗?

检查文件Makefile.VSL中的include和library路径,修改为与本机一致;

先编译运行原始算法程序,输入:nmake –f Makefile.rand,生成文件pimonte_rand.exe,运行它并记录结果;再编译运行VSL改进算法程序,输入:nmake –f Makefile.VSL,生成文件pimonte_VSL.exe,运行它并记录结果;

改变环境变量OMP_NUM_THREADS,设置不同的线程数量,观察结果有什么变化。

有关编译器优化的更完整信息,请参阅优化通知