原文:《SparkCL: A Unified Programming Framework for Accelerators on Heterogeneous Clusters》
翻译:
概要:我们提出SparkCL,这是一个基于Java、OpenCL和Apache Spark框架的开放源码统一编程框架。这项工作的动机是将诸如fpgas/gpus/apus/DSPs等非传统的计算核心,以及未来的核心类型引入到主流编程的使用中。该框架允许在Spark框架下对不同计算设备进行同等处理,并引入了将计算卸载到加速设备的能力。这个新框架通过一个java opencl设备编程层无缝集成到标准Spark框架中,该层基于Aparapi和Spark编程层,其中包括新的内核函数类型和修改的Spark转换和动作。该框架允许单个代码基针对支持OpenCL的任何类型的计算核心,并将新的核心类型轻松地集成到Spark集群中。
1.引言
从理论上[1]和实践中[2],数据中心[3]和HPC[4]应用程序可以从使用不同类型的计算核心中受益,从而实现计算密集型目标。这样做的好处是提高了整个系统的效率和性能。在green 500列表[5]中不断增长的异构系统列表中,可以找到几个主要的例子。一个异构系统通常由传统的核心(cpu)和非传统的核心(gpus/fpgas/dsps)组成。这样的系统在不同类型的任务上使用传统和非常规的核心。异构计算通过专门化提高了性能和效率。
硬件专门化的主要困难之一是不同类型的硬件设备需要不同类型的编程语言、开发工具和技术技能集来掌握它们。即使从软件开发的角度来看,代码行数的增加也会导致系统不稳定性的增加[6]。
为了使异构计算成为主流系统的设计选择,需要采用标准来对各种设备进行编程。自2008年推出以来,OpenCL[7]的一个标准已经开始增长。在过去的几年中,它正在成为一个行业的选择,支持跨越多个架构,尽管不是没有来自提供他们自己的专门软件开发环境的制造商的抵制。
OpenCL虽然朝着正确的方向迈出了一大步,但对于许多软件工程师来说仍然是一个困难的挑战[8]。需要处理OpenCL的技术细节,以及在数据中心等许多开发环境中,c/c++不是首选语言的事实,妨碍了它成功和主流应用的机会。
在大数据处理的时代,我们已经在过去的几年里了。我们需要处理大量的数据,并预测我们将很快进入exascale计算的时代,在今天的标准上,数据和计算的数量增加了上千倍,这是寻找更高效的计算解决方案的主要动力。到目前为止,我们还远未达到美国能源部为2020年制定的“exascale”能源效率目标[9]。为了实现这些目标,我们需要在设计和规划大型系统的方式上做出重大改变。此外,预计异构将在未来的exascale系统中发挥重要作用。
今天的主流数据处理框架,如Spark[1]1和Hadoop[12],将计算机视为传统核心的集合。如果他们真的利用了非传统的核心,那就是通过专门的库,通常是GPU类型的[13]。在计算环境中,他们不会把非传统的核心视为平等的公民,而且他们也不可能轻易地将新类型的非常规核心集成到他们中间。
SparkCL是一种试图改变现状的尝试,它允许一个主流框架(Spark)将非传统核心整合到其核心业务中。为了实现这个目标,我们引入了两个开源软件
框架:aparapi-ucores[17]和spark-ucores(代号SparkCL)[16]。它们一起允许单个java代码库被发送到Spark工作者,如果可用的话,可以通过专门的硬件加速。
本文的其余部分按如下方式组织。第二节给出了SparkCL框架的概述,第3部分讨论了执行模型和添加到Spark的新功能。第四节讨论了一些相关的工作,第5节和第6节分别讨论了结论和未来的方向。
2.SparkCL综述
我们将两个独立的开源框架的力量结合在一起:Aparapi和Spark创建了一个新的框架,允许使用简单的java代码在Aparapi和Spark框架上运行,从而加速执行。
图1 框架综述
正如在图1中所看到的,用Java编写的用户执行内核将由SparkCL框架执行,该框架将代码激发并最终在集群上的OpenCL功能设备上启动。为了允许这种编程流,在非传统核心的处理中,一个新的编程层是在现有的Spark和Aparapi基础设施之上构建的。
3.Spark层的修改
Spark和其他大数据框架一样,将计算机视为核心集合。当涉及到执行一般计算功能时,它不会考虑到非常规的核心。为了适应非常规
我们必须修改函数和数据被发送到加速度设备的方式。在我们之前的关于加速Hadoop框架的工作中[14,15],我们已经确定了几个关键问题:
1)一个任务必须是计算密集型的,以证明使用加速器的开销是合理的,例如,对架构的限制、数据传输的开销,以及大多数加速器在计算结构中集成的方式在今天完成,很难加速计算简单的任务。相反,重点应该放在高度计算密集型任务上。
2)必须收集足够的数据,以实现有效的加速。在大多数情况下,为了有效的加速,需要计算复杂度和大量数据的组合。
3)高水平的大数据编程框架倾向于帮助用户推广他们的算法,使他们远离底层硬件的有效操作的关注。这意味着内存分配和设备友好型数据类型不是它们强大的套件或关注点。
为了能够有效地利用加速器,我们需要解决前面提到的问题,然后才能实现有效的集成和加速。
3.1执行模型和内核类型
在标准Spark中,一个函数有一个单独的调用站点,并在集群中复制。这对于cpu来说是足够的,但是不允许加速器的特殊要求,即大量的原始类型数据和复杂的计算。为了满足这些需求,我们创建了一个我们称为SparkKernel类型的东西。这种类型封装了一个运行函数,一个Aparapi内核(具有类似于标准Spark中现有call覆盖的功能),还有两个额外的功能,用于在运行内核并在内核执行后对数据进行后期处理之前准备/预处理数据。
public abstract class SparkKernel<T,R> extends SparkKernelBase implements Serializable { public abstract void mapParameters(T data); public abstract void run(); public abstract R mapReturnValue(T data); }
|
图2 Spark Kernel
如图2可以看到一个抽象内核类型的例子。用户使用三个函数的实现覆盖抽象的内核类型。
3.1.1 核函数重写
下面是应该在用户的内核中覆盖的标准函数。
3.1.1.1 void mapParameters(T数据)
准备数据并决定使用哪一种设备。用户可以使用API来做一些事情,比如设置计算范围,选择执行模式(cpu/加速器/jtp),如果条件不理想运行加速版本,则有选择地运行内核,例如,在没有足够的数据来证明内核执行的情况下。
3.1.1.2 void run()
一个标准的Aparapi内核,它将在集群上的每个功能设备节点上执行。该框架将尝试在默认情况下缓存它,以避免每个工作者节点上的多个实例化。
3.1.1.3 R mapReturnValue(T数据)
发布数据并处理任何需要的内核执行的活动或清理。如果内核没有被选择性地执行,我们可以在这里调用另一个计算函数。
3.1.2 简单的用户内核的例子
RddTestArray rddTestArrayRes = SparkUtil.genSparkCL(rddTest1).reduceCL(new SparkKernel2<RddTestArray>() { // data float[] a; float[] b; float[] c;
@Override public void mapParameters(RddTestArray data1, RddTestArray data2) { a = data1. getDataArray(); b = data2. getDataArray(); c = new float[a.length]; setRange(Range.create(c.length)); }
@Override public void run() { int gid = getGlobalId(); c[gid] = a[gid] + b[gid]; }
@Override public RddTestArray mapReturnValue(RddTestArray data1, RddTestArray data2) { return new RddTestArray(c); } }); |
图3 向量相加例子
如图3所示。显示一个简单的向量添加内核,内核的核心是一个简单的两个行代码段,如果可用的话,它将在加速硬件上执行。映射参数和映射返回促进了内核的预/post处理。在开放源码SparkCL框架分发[16]中,可以找到与源代码相关的完整示例。
3.1.3 SparkCL转换和动作
标准的Spark动作,如映射和转换,如减少需要被移植到新框架中。SparkCL引入了三个这样的新结构:
1)MapCL-使用Spark风格的地图函数映射一个SparkCL内核。
2)MapCLPartition——使用Spark样式的Map分区函数映射一个SparkCL内核。
3)reduceCL-用Spark风格的treeReduce函数映射一个SparkCL内核。
3.1.4 aparapi UCores集成
在SparkCL集成完成之后,内核被发送到一个标准的Spark工作者,以及基于Java的基于Java的库。该工作人员将使用Aparapi UCores框架[17]来执行内核。Aparapi UCores是一个分支框架[18]。标准的Aparapi库已经被扩展,以支持二进制执行流(支持fpga和其他设备的可选)、加速器类型和平台选择支持,以方便地集成到多个OpenCL环境和大数据框架中。
3.1.5 Worker设置和Spark集成
一个SparkCL worker是一个标准的Spark worker,它能够同时运行加速和非加速的任务,也就是标准的Spark任务。这一能力的关键是以下因素:
1)一个SparkCL Worker是一个未修改的Spark Worker类org.apache.spark.deploy.worker.Worker
2)如果一个标准的Spark job被发送到内核,它将使用标准的Worker类功能来执行。
3)如果将一个SparkCL job发送给worker,SparkCL扩展将接管并处理加速。
4)一个SparkCL worker使用启动脚本执行,确保它与节点上的OpenCL规范/通用(ICD)实现绑定。
5)一个Worker可以在启动(device/framework)上设置其首选的OpenCL方向,并且用户可以对其进行彻底的修改。
为了帮助完成上面的内容,在发行版中包含了一个简单的启动脚本:
scripts/spark-submit-and-set-env.sh [OpenCL实现体系][结构][设备类型]OpenCL实现——现在可以是std或fpga。注意,std意味着任何兼容的OpenCL实现(amd/intel/nvidia等)。
结构——amd/intel/nvidia等等,这个字符串被发送到Aparapi UCores来过滤可用的平台。这是您选择您希望工人绑定到的OpenCL平台的地方。
设备类型——选定的默认加速设备可以是cpu/acc/jtp。此外,内核代码可以选择在m服装功能中以编程方式在设备之间切换。此外,内核代码可以选择在mapParameters函数中以编程方式在设备之间切换。
// start an Altera FPGA worker -> scripts/spark-submit-and-set-env.sh fpga Altera ACC spark-1.3.0-bin- hadoop2.4/bin/spark-class org.apache.spark.deploy.worker.Worker -- cores 1 spark://192.168.0.112:7077 // start an AMD APU worker (GPU preferred mode) -> scripts/spark-submit-and-set-env.sh std AMD GPU spark-1.3.0-bin- hadoop2.4/bin/spark-class org.apache.spark.deploy.worker.Worker -- cores 1 spark://192.168.0.112:7077 // start an AMD APU worker (CPU preferred mode) -> scripts/spark-submit-and-set-env.sh std AMD CPU spark-1.3.0-bin- hadoop2.4/bin/spark-class org.apache.spark.deploy.worker.Worker -- cores 1 spark://192.168.0.112:7077 |
图4 worker执行模型
在图4中可以看到如何在单个节点上启动不同类型的woerkers的示例。这个特定节点有两个OpenCL实现(altera/amd)和三种类型的设备FPGA、GPU和CPU。我们可以使用不同的设备类型来启动三种不同的workers。注意,出于Spark调度的目的,在上面的示例中,我们告诉worker使用一个核心。通过这种方式,它将按顺序发送加速任务,并且它们不会在相同的硬件加速资源上竞争。SparkCL有防止争用的条款,但是这种方法完全避免了潜在的冲突。
3.2 示例应用
为了演示框架的操作,我们在SparkCL中实现了三种算法。它们可以在分布式开源项目[16]中找到。
3.2.1 SparkCLPi
基于MapCL内核变体的一个SparkCL分布的Pi计算。有几个实现,包括一个优化的标准Spark,它比标准Spark分布式在性能测试中提供的速度要快得多。所有的Pi测试都可以通过命令行从命令行启动,以便进行轻松的性能比较测试。
3.2.2 SparkCLVectorAdd
基于简化的内核类型的一个SparkCL分布的向量加法。如果有足够的工作,它会在可能加速的worker上执行,而不是在单个驱动程序上(使用SparktreeReduce而不是reduce)。
3.2.3 SparkCLWordCount
基于MapCL内核类型的一个SparkCL分布式单词计数应用程序。它是Spark示例的功能复制,但在SparkCL中实现了。它展示了一个更复杂的内核,带有本地数据和选择性执行。
4. 相关工作
近年来,[18,19和20]开发了几个基于OpenCL的高级编程框架。尽管这些库支持OpenCL,但它们的重点是GPU和CPU开发。有几次尝试加速Hadoop框架,涉及使用改进的MapReduce框架来适应加速器[21、22]的限制和优点。以前在fpga上加速Hadoop K_MEANS的尝试显示了良好的前景,但涉及到重大的开发工作[14,15]。其他几个试图创造加速器框架,但在所有这些尝试集中在gpu上遗漏了其他类型的加速器,因此他们没有完全采用非常规核心的更广泛的前提,每个加速器都有优点和缺点,不同类型的加速器应该用于解决不同的计算任务。
5. 总结
我们引入了SparkCL,这是一个基于Apache Spark和Aparapi的开源高级Java OpenCL框架,它能够在不同的平台和设备上运行高性能和以数据为中心的应用程序,希望它对异构系统用户和研究社区有帮助。我们提供了在异构集群中跨不同架构使用单个高水平的Java-OpenCL代码库的潜力,以便在尝试利用异构计算的能力和效率的同时,最大化代码重用。
6. 未来的发展方向
我们计划继续在SparkCL框架上工作,希望其他人会发现它有用,并加入开发和扩展SparkCL框架的工作。这个项目还处于起步阶段,在优化、设置和可用性方面有很多需要,我们设想了一个易于使用和安装的框架,以便任何与电力效率相关的程序员/研究人员,在不了解底层架构和硬件的情况下,可以使用这个系统。
7. 致谢
我们要感谢Altera、Nallatech、HP和Terasic在过去几年中在这一系列研究的不同阶段的支持和硬件贡献。
8. 参考文献
- Chung, Eric S., et al. "Single-chip heterogeneous computing: Does the future include custom logic, FPGAs, and GPGPUs?." Proceedings of the 2010 43rd Annual IEEE/ACM International Symposium on Microarchitecture. IEEE Computer Society, 2010.
- S. Huang, S. Xiao, and W. Feng. 2009. On the energy efficiency of graphics processing units for scientific computing. In Proceedings of the 2009 IEEE International Symposium on Parallel&Distributed Processing (IPDPS '09). IEEE Computer Society, Washington, DC, USA, 1-8.
- Chalamalasetti, S.; Margala, M.; Vanderbauwhede, W.; Wright, M.; Ranganathan, P., "Evaluating FPGA- acceleration for real-time unstructured search," Performance Analysis of Systems and Software (ISPASS), 2012 IEEE International Symposium on , vol., no., pp.200,209, 1-3 April 2012.
- Gan, Lin, et al. "Accelerating solvers for global atmospheric equations through mixed-precision data flow engine." Field Programmable Logic and Applications (FPL), 2013 23rd International Conference on. IEEE, 2013.
- The Green500 List (11/2014). http://www.green500.org/news/green500-list- november-2014
- Steve McConnell. 1993. Code Complete: A Practical Handbook of Software Construction. Microsoft Press, Redmond, WA, USA.
- Khronos OpenCL Working Group. "OpenCL-The open standard for parallel programming of heterogeneous systems." On line] http://www. khronos. org/opencl (2011).
- TIOBE Index. http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
- J. a. D. S. a. M. J. Shalf, "Exascale computing technology challenges," in High Performance Computing for Computational Science--VECPAR 2010, Springer, 2011, pp. 1--25.
- Dongarra, Jack. "The international exascale software project roadmap." International Journal of High Performance Computing Applications (2011): 1094342010391989.
- Zaharia, Matei, et al. "Spark: cluster computing with working sets." Proceedings of the 2nd USENIX conference on Hot topics in cloud computing. 2010.
- Apache Hadoop. http://hadoop.apache.org/
- Canny, John. "Interactive Machine Learning." University of California, Berkeley (2014).
- Segal, Oren, et al. "High level programming framework for FPGAs in the data center." Field Programmable Logic and Applications (FPL), 2014 24th International Conference on. IEEE, 2014.
- Segal, Oren, et al. "High Level Programming for Heterogeneous Architectures." arXiv preprint arXiv:1408.4964 (2014).
- Spark for Unconventional Cores (SparkCL). https://gitlab.com/mora/spark-ucores
- Aparapi for Unconventional Cores. https://gitlab.com/mora/aparapi-ucores
- Aparapi. API for data parallel Java, http://code.google.com/p/aparapi/.
- JavaCL. http://code.google.com/p/javacl/
- Ruby-OpenCL. http://ruby-opencl.rubyforge.org/
- He, Bingsheng, et al. "Mars: a MapReduce framework on graphics processors." Proceedings of the 17th international conference on Parallel architectures and compilation techniques. ACM, 2008.
- Basaran, Can, and Kyoung-Don Kang. "Grex: An efficient MapReduce framework for graphics processing units." Journal of Parallel and Distributed Computing 73.4 (2013): 522-533.