释放大数据分析和机器学习的力量
为了帮助创新者应对机器学习的复杂性,我们通过熟悉的 Intel® 软件工具,特别是 Intel® 数据分析加速库 (Intel® DAAL) 和 Intel® 数学核心库的增强功能,为开发人员提供性能优化。
点击此处注册并下载免费的 Intel® Parallel Studio XE 30天试用版.
我们生活在一个人类越来越依赖计算机来解决各种工程问题的世界——从天气预报到救命药物的发现。我们正处于另一个戏剧性变革的边缘,机器在决策和解决复杂问题的能力方面能够达到甚至超越人类。计算机已经在 Jeopardy* 和 围棋* 中击败了最优秀的人类选手,自动驾驶汽车正在加州的道路上行驶。这一切都得益于 petaflops 级别的计算能力(感谢摩尔定律)以及用于训练机器学习算法的大量数据。
在英特尔,我们与领先的学术界和工业界同行紧密合作,为英特尔即将推出的多核/众核计算平台解决硬件和软件架构挑战。为了帮助创新者应对机器学习的复杂性,我们通过熟悉的 Intel® 软件工具,特别是 Intel® 数据分析加速库 (Intel® DAAL) 和 Intel® 数学核心库 (Intel® MKL) 的增强功能,为开发人员提供性能优化。
机器学习的挑战
在过去的十年里,机器学习是一个增长极其快速的学科。这种增长得益于互联网产生了海量数据。从数据中提取模式并应用这些知识进行预测的愿望促使了新方法和算法的开发。计算能力的指数级增长使得将这些算法应用于海量数据集并做出有用的预测成为可能。
深度神经网络 (DNN) 是机器学习领域的尖端技术。这些算法在 20 世纪 90 年代末获得广泛的行业采纳,最初应用于银行支票上的手写识别等任务。深度神经网络在这些任务上取得了广泛成功,能够与甚至超越人类的能力。如今,DNN 已被用于图像识别、视频和自然语言处理,以及解决复杂的视觉理解问题,例如自动驾驶所带来的问题。DNN 对计算资源和必须处理的数据量要求极高。为了说明这一点,现代图像识别拓扑 AlexNet 在现代计算系统上需要数天才能训练完成,并且使用略多于 1400 万张图像。要应对这种复杂性,需要高度优化的构建块来缩短训练时间并满足工业应用的需求。
Intel MKL
Intel MKL 是适用于 Intel 和兼容架构的高性能数学库(**图 1**)。该库提供了常用稠密(BLAS 和 LAPACK)和稀疏(Sparse BLAS 和 Intel® MKL PARDISO)线性代数例程、离散傅立叶变换、向量数学以及针对当前和未来 Intel® 处理器优化的统计函数的实现。Intel MKL 利用指令、线程和集群级别的并行性来提高工作站、服务器和超级计算机上众多科学、工程和金融应用的性能。
虽然 Intel MKL 是为高性能计算 (HPC) 设计的,但其功能与数学本身一样普遍。矩阵-矩阵乘法、快速傅立叶变换 (FFT) 或高斯消元等函数不仅为许多科学和工程问题奠定了基础,也为机器学习算法奠定了基础。
Intel MKL 2017 包含优化的功能,可为关键的机器学习算法带来优势,并新增了 DNN 扩展以满足机器学习独特的计算需求。我们将重点介绍其中两个:深度神经网络扩展和矩阵-矩阵乘法改进。
使用 Intel MKL 加速 DNN
Intel MKL 中的 DNN 原语
深度学习是机器学习的一个分支,它使用具有多个处理层的深度图来建模高级抽象,并正在迅速占领数据中心。这种方法受到了生物体通过视觉皮层感知现实方式的启发。它在图像和视频识别、自然语言处理以及推荐系统等应用中取得了广泛成功。这些工作负载依赖于许多算法,其中最主要的是多维卷积和矩阵-矩阵乘法。虽然卷积可以表示为矩阵乘法,但有时更有效的方法是采用直接方法,从而在现代架构上产生明显更好的性能。
除了卷积之外,深度学习工作负载还包括几种对小尺寸矩阵进行操作的层。为了最大限度地减少数据转换的开销,我们在 Intel MKL 2017 的新深度神经网络 (DNN) 域中引入了这些关键功能的优化实现。
Intel MKL 2017 引入了 DNN 域,其中包含加速最受欢迎的图像识别拓扑(包括 AlexNet、VGG、GoogLeNet 和 ResNet)所需的功能。
这些 DNN 拓扑依赖于许多标准构建块(或原语),这些原语对多维数据集(称为张量)形式的数据进行操作。原语包括卷积、归一化、激活和内积函数,以及操作张量所需的功能。在 Intel 架构上有效执行计算需要通过矢量化利用 SIMD 指令,并通过线程利用多个计算核心。矢量化极其重要,因为现代处理器处理长达 512 位的向量数据(16 个单精度数字),并且每个周期可以执行最多两次乘法和加法(融合乘加,或 FMA)运算。利用矢量化需要数据在内存中连续存储。由于张量的典型维度相对较小,更改数据布局会引入显著的开销。我们努力在不更改原语之间数据布局的情况下执行拓扑中的所有操作。
Intel MKL 为大多数常用操作提供了原语,这些操作已针对对矢量化友好的数据布局进行了实现
- 直接批处理卷积
- 内积
- 池化:最大值、最小值、平均值
- 归一化:跨通道的局部响应归一化 (LRN)、批归一化
- 激活:ReLU(整流线性单元)
- 数据操作:多维转置(转换)、分割、连接、求和以及缩放
神经网络拓扑的执行流程包括两个阶段:设置和执行。在设置阶段,应用程序会创建实现评分、训练或其他特定于应用程序的计算所需的全部 DNN 操作的描述。为了将数据从一个 DNN 操作传递到下一个操作,某些应用程序会创建中间转换并分配临时数组,前提是适当的输出和输入数据布局不匹配。此阶段通常在应用程序中执行一次,之后是多次执行阶段,在此期间进行实际计算。
在执行步骤(**图 2**)中,数据以 NCWH(批次、通道、宽度、高度)等平面布局输入网络,并转换为 SIMD 友好的布局。当数据在层之间传播时,数据布局保持不变,并在需要执行现有实现不支持的操作时进行转换。
案例研究:Caffe*
Caffe* 是由伯克利视觉与学习中心 (BVLC) 开发的一个深度学习框架,也是最受欢迎的图像识别社区框架之一。与用于图像识别的神经网络拓扑 AlexNet 和标记图像数据库 ImageNet 一起,Caffe 通常用作基准。
Caffe 已利用 Intel MKL 提供的优化数学例程,通过标准的 BLAS 接口。然而,原始实现未能有效利用并行性,并且在卷积实现中未能充分利用 GEMM 函数。通过重构计算流程使用较大矩阵上的 GEMM,并借助 OpenMP* 提取更多并行性,我们在使用双路 Intel® Xeon® 处理器 E5-2699 v4 的系统上训练 AlexNet 拓扑时实现了 5.8 倍的加速。如前所述,直接卷积实现更有效。通过使用新的 Intel MKL 2017 原语,我们实现了 11 倍的加速。
Intel 架构和 Intel MKL 持续发展。今年 6 月,我们推出了 Intel® Xeon Phi™ 处理器 x200 系列,该系列处理器具有大规模并行架构,包含多达 72 个核心、Intel® 高级矢量扩展 512 (Intel® AVX-512) 和快速片上内存。在单路 Intel Xeon Phi 处理器 7200 上使用启用了新 Intel MKL 原语的英特尔 Caffe 分支,可实现额外 2 倍的加速(**图 3**)。
使用 Intel® 数学核心库 (Intel® MKL) 提高深度神经网络工作负载的性能
更快的矩阵-矩阵乘法
矩阵-矩阵乘法 (GEMM) 是许多科学、工程和机器学习应用中的基本运算。对该运算进行优化的需求持续存在。Intel MKL 提供并行、高性能的 GEMM 实现。为了提供最佳性能,Intel MKL 的 GEMM 实现通常会将原始输入矩阵转换为最适合目标平台的内部数据格式。这种数据转换(也称为打包)可能成本很高,尤其对于一个或多个维度较小的输入矩阵。Intel MKL 2017 引入了 [S,D]GEMM 打包应用程序接口 (API),以避免重复打包。这可以改善某些矩阵大小和机器学习用例的性能。
这些 API 允许用户显式地将矩阵转换为内部打包格式,并将打包的矩阵(或矩阵)传递给多个 GEMM 调用。通过这种方法,如果输入矩阵 (A 或 B) 在这些调用之间被重用(如在循环神经网络中可能发生的那样),则打包成本可以分摊到多个 GEMM 调用上。
使用 Intel® 数学核心库 (Intel® MKL) 提高深度神经网络工作负载的性能 有关编译器优化的更完整信息,请参阅我们的优化声明。订阅未来期刊与朋友分享 The Parallel Universe 23
示例
下面显示的三个 GEMM 调用使用相同的 A 矩阵,而 B/C 矩阵对每个调用都不同
float *A, *B1, *B2, *B3, *C1, *C2, *C3, alpha, beta; MKL_INT m, n, k, lda, ldb, ldc; // initialize the pointers and matrix dimensions (skipped for brevity) sgemm("T", "N", &m, &n, &k, &alpha, A, &lda, B1, &ldb, &beta, C1, &ldc); sgemm("T", "N", &m, &n, &k, &alpha, A, &lda, B2, &ldb, &beta, C2, &ldc); sgemm("T", "N", &m, &n, &k, &alpha, A, &lda, B3, &ldb, &beta, C3, &ldc);
在此,A 矩阵在每次 sgemm 调用中都转换为内部打包数据格式。如果 n 很小(B/C 的列数),则将 A 矩阵打包三次产生的相对成本可能很高。通过将 A 矩阵打包一次,并为三个连续的 GEMM 调用使用其打包的等效形式,可以最大限度地降低此成本,如下所示。
// allocate memory for packed data format float *Ap; Ap = sgemm_alloc("A", &m, &n, &k); // transform A into packed format sgemm_pack("A", "T", &m, &n, &k, &alpha, A, &lda, Ap); // SGEMM computations are performed using the packed A matrix: Ap sgemm_compute("P", "N", &m, &n, &k, Ap, &lda, B1, &ldb, &beta, C1, &ldc); sgemm_compute("P", "N", &m, &n, &k, Ap, &lda, B2, &ldb, &beta, C2, &ldc); sgemm_compute("P", "N", &m, &n, &k, Ap, &lda, B3, &ldb, &beta, C3, &ldc); // release the memory for Ap sgemm_free(Ap);
上面的代码示例使用了为支持 GEMM 的打包 API 而引入的四个新函数:sgemm_alloc、sgemm_pack、sgemm_compute 和 sgemm_free。首先,使用 sgemm_alloc 分配打包格式所需的内存,该函数接受一个标识打包矩阵(此处为 A)的字符参数和三个矩阵维度的整数参数。然后,sgemm_pack 将原始 A 矩阵转换为打包格式 Ap 并执行 alpha 缩放。原始 A 矩阵保持不变。三个 sgemm 调用被替换为三个 sgemm_compute 调用,这些调用使用打包矩阵并假设 alpha=1.0。sgemm_compute 的前两个字符参数表示 A 矩阵是打包格式(“P”),B 矩阵是未转置的列主序格式(“N”)。最后,通过调用 sgemm_free 释放为 Ap 分配的内存。
GEMM 打包 API 消除了在此示例中为三个矩阵-矩阵乘法运算重复打包矩阵 A 的成本。如果 A 和/或 B 在 GEMM 调用之间被重用,则这些打包 API 可用于消除 A 和/或 B 输入矩阵的数据转换成本。
性能
**图 4** 显示了在 Intel® Xeon Phi™ 处理器 7250 上使用打包 API 的性能提升。假设可以通过大量使用相同 A 矩阵的 SGEMM 调用完全分摊打包成本。为了进行比较,还提供了常规 SGEMM 调用的性能。
实现说明
建议使用相同数量的线程调用 gemm_pack 和 gemm_compute 以获得最佳性能。请注意,如果共享相同 A 或 B 矩阵的 GEMM 调用数量很少,则打包 API 可能只会带来很小的性能提升。
gemm_alloc 例程分配的内存量约等于原始输入矩阵的大小。这意味着对于大型输入矩阵,应用程序的内存需求可能会显著增加。
GEMM 打包 API 仅在 Intel MKL 2017 的 SGEMM 和 DGEMM 中实现。它们适用于所有 Intel 架构,但仅针对 64 位 Intel® AVX2 及以上版本进行了优化。
Intel DAAL
在很大程度上,机器学习和深度学习算法的日益普及和采用得益于可用于算法训练的数据的快速增长。“大数据”一词有多种定义;我们将从其三个主要属性:多样性、速度和体量来讨论大数据。这些大数据属性中的每一个都需要特殊的计算解决方案,而 Intel DAAL 的设计目的就是为了解决所有这些问题。
Variety(多样性)
我们所说的*多样性*,是指结构化和非结构化数据生成的多种来源和类型,这为数据提取和进一步分析带来了一定的挑战。为了解决大数据的这一属性,Intel DAAL 引入了数据管理组件作为库的重要组成部分。这包括用于数据采集、初始预处理和规范化、将数据从多种支持的数据源转换为数值格式以及模型表示的类和实用程序。由于在实际分析应用程序中,您可能会在应用程序的任何部分发现瓶颈,因此 Intel DAAL 专注于优化整个数据流。它提供了涵盖数据分析所有阶段的优化构建块:从数据源采集数据、预处理、转换、数据挖掘、建模、验证和决策(**图 5**)。
此外,Intel DAAL 同时支持同构和异构数据,并在必要时执行中间数据转换。它还支持稠密和稀疏数据类型,并提供可处理噪声数据的算法。
速度
计算速度在当今的商业环境中至关重要。大数据的最重要方面之一是它通常是实时发生的,并且需要快速的响应时间。Intel DAAL 的设计旨在帮助软件开发人员减少开发应用程序的时间并以更高的性能交付它们。Intel DAAL 有助于应用程序更快地做出更好的预测,并能根据可用的计算资源进行扩展。它依赖于 Intel MKL 构建块,并提供额外的算法优化,以在 Intel 架构上实现最大性能提升。Intel DAAL 提供 C++、Java* 和 Python* 语言的 API。这允许用户快速原型化模型并轻松将其部署到大型集群环境。
卷
大数据意味着海量数据,可能大到无法放入内存。数据集合分布在集群的不同节点或各种设备上的情况也非常普遍。为了解决这个问题,Intel DAAL 算法支持批处理、在线和分布式处理这三种计算模式。
在批处理模式下,算法使用整个数据集来生成最终结果。当整个数据集在当前不可用时,或者当数据集不适合设备内存时,会发生更复杂的场景,这需要其他两种处理模式。
在在线处理模式下,算法通过逐步更新部分结果来处理分块传入设备内存的数据集,并在处理完最后一个数据块后将结果定型。
在分布式处理模式下,算法在分布在多个设备(计算节点)上的数据集上运行。算法在每个节点上生成部分结果,这些结果最终在主节点上合并成最终结果。
由于存在许多可用于分布式计算的平台,Intel DAAL 中的分布式算法已抽象为底层跨设备通信技术。这使得该库可以在各种多设备计算和数据传输场景中使用,包括(但不限于)MPI-、Hadoop*-或 Spark*-集群环境。虽然用户需要实现跨设备通信,但 Intel DAAL 提供了示例,演示了如何将该库与最常见的分析平台一起使用。
Intel DAAL 在不同计算模式下的使用
批处理模式
所有 Intel DAAL 算法都支持批处理计算模式,并且以这种方式使用它相对容易。在批处理模式下,只需使用特定算法类的 compute 方法。只需选择要使用的算法,设置输入数据和算法参数,运行 compute 方法,然后即可访问结果。下面的示例演示了如何在批处理模式下使用 Intel DAAL 进行 Cholesky 分解算法
// Create an algorithm to compute Cholesky decomposition using the default method cholesky::Batch<> cholesky_alg; // Set input data cholesky_alg.input.set(cholesky::data, dataSource.getNumericTable()) // Run compute cholesky_alg.compute(); // Get access to results of computation services::SharedPtr<cholesky::Result> res = cholesky_alg.getResult()
在线处理模式
某些 Intel DAAL 算法支持分块处理数据集。在线处理计算模式的 API 与批处理模式类似,区别在于您需要每次可用数据时运行 compute 方法,然后调用 `finalizeCompute` 在最后合并结果。下面的示例演示了如何在在线处理模式下使用 Intel DAAL 进行奇异值分解 (SVD) 算法
// initialize SVD algorithm svd::Online<double, defaultDense> algorithm; // Process data blocks within a loop Status loadStatus; while((loadStatus = dataSource.loadDataBlock(nRowsInBlock)) == success) { // set input data algorithm.input.set( svd::data, dataSource.getNumericTable() ); // run compute algorithm.compute(); } // Finalize the computations and retrieve SVD results algorithm.finalizeCompute(); SharedPtr<svd::Result> res = algorithm.getResult(); // Access results printNumericTable(res->get(svd::singularValues), "Singular values:");
分布式处理模式
某些 Intel DAAL 算法支持处理分布在多个设备上的数据集。根据算法的不同,您可能需要采用不同的计算方案。这可以是从简单的 MapReduce(第一步在本地节点上执行,最后一步在主节点上执行)到更复杂的 MapReduce-Map 等方案。Intel DAAL 编程指南包含演示如何将 Intel DAAL 与 Hadoop、Spark 或 MPI 结合使用的示例。下面的示例演示了如何在分布式处理模式下使用 Intel DAAL 进行主成分分析 (PCA) 算法
Step 1: On local nodes (Mapper) // Create algorithm to compute PCA decomposition using SVD method on local nodes DistributedStep1Local pcaLocal = new DistributedStep1Local(daalContext, Double.class, Method.svdDense); // Set input data pcaLocal.input.set( InputId.data, ntData ); // Compute PCA on local nodes PartialResult pres = pcaLocal.compute(); // Prepare data for sending to master node context.write(new IntWritable(0), new WriteableData(index, pres)); Step 2: On Master node // Create algorithm to calculate PCA decomposition using SVD method on master node DistributedStep2Master pcaMaster = new DistributedStep2Master(daalContext, Double.class, Method.svdDense); // Add input data as it arrives from local nodes for (WriteableData value : values) { PartialResult pr = (PartialResult)value.getObject(daalContext); pcaMaster.input.add( MasterInputId.partialResults, pr); } // Compute PCA on master node pcaMaster.compute(); // Finalize the computations and retrieve PCA results Result res = pcaMaster.finalizeCompute(); HomogenNumericTable eigenValues = (HomogenNumericTable)res.get(ResultId.eigenValues );
性能数据
**图 6** 显示了 Intel 数据分析加速库 (Intel DAAL) 在 8 节点 Hadoop 集群上与 Spark MLlib 的性能对比。
Intel DAAL 2017 的新功能
Intel DAAL 2017 引入了许多新功能,其中最引人注目的是神经网络功能的实现。它包含多个组件,允许用户轻松构建和运行各种神经网络拓扑,从图像分类和对象跟踪到金融市场预测。为了支持这些各种用例,Intel DAAL 引入了几个关键的神经网络构建块(**图 7**)
- 层:NN 构建块,单个层的正向和反向版本。
- 拓扑:表示 NN 配置的结构(例如,AlexNet)。
- 模型:根据定义的拓扑连接的一组层、它们的参数(权重和偏差)以及服务例程。
- 优化求解器:根据指定的客观函数在正向-反向传播后更新权重和偏差。
- NN:管理 NN 计算流程的驱动程序。在训练期间,驱动程序会遍历拓扑执行正向和反向传播,并使用优化求解器更新参数。在评分期间,它通过应用正向传播返回预测结果。
- 多维数据结构(张量):用于表示复杂数据(例如,3D 图像流)的结构。
通过与传统机器学习算法相同的 API,数据科学家可以轻松地比较使用神经网络创建的模型与支持向量机 (SVM) 或线性回归等传统机器学习算法的准确性,同时在 Intel 架构上获得出色的性能。该库的特性揭示了将神经网络与其他算法结合使用的可能性(例如,将神经网络模型作为弱学习器注入到提升算法中)。
应对大数据和机器学习的挑战
处理大数据分析和机器学习通常需要开发人员使用不同的编程语言、工具和库来解决问题。数据经常来自各种来源,并且可能是异构的、稀疏的或有噪声的。Python 等脚本语言通常在原型设计阶段使用,而 C/C++ 语言则用于优化数据流中最关键的部分。真实数据会随着时间到来,并且/或者通常不适合单个计算机的内存,因此需要使用 MPI、Hadoop 或 Spark 等分布式系统进行有效的数据处理。
鉴于所有这些因素,开发、测试和支持过程需要开发人员具备多个领域的知识。将许多解决方案集成到单个应用程序中需要时间。结果是开发时间大大增加,大数据分析的采用也因此延迟。
Intel DAAL 的设计旨在应对所有这些挑战,并覆盖开发人员在处理大数据时可能遇到的几乎所有可能的用例。该库专注于优化整个数据流,而不仅仅是算法部分,并提供涵盖数据分析所有阶段的优化构建块:从数据源采集数据、预处理、转换、数据挖掘、建模、验证和决策。使用相同的 API,可以将模型从单个节点扩展到大型集群。Intel DAAL 与 Intel MKL 一起,可以帮助释放大数据分析和机器学习的强大功能。