强强联合,性能提升数倍!Alibaba Dragonwell11+VectorAPI 助力 Java 高性能新时代

简介: VectorAPI 是 Java 在特定领域进行高性能计算的利器。

文/朱文杰、金钟晖

01 背景

Alibaba Dragonwell 作为 OpenJDK 的下游版本,是阿里巴巴针对 10万+ 服务器上运行的在线电商、金融、物流应用优化的 OpenJDK 实现。 阿里巴巴和 OpenJDK 社区紧密合作,将尽可能多的 Alibaba Dragonwell 定制功能带到上游。Dragonwell 是 OpenAnolis 的默认 JDK,Alibaba 的众多 Java 应用,正在逐步迁移到 Dragonwell 上。


Intel Java 团队长期致力于 OpenJDK 的发展,贡献了大量优化特性,这些工作使得 OpenJDK 可以更好利用现代 CPU 的强大特性。VectorAPI 是 Java 在特定领域进行高性能计算的利器,广大 Java 开发者通过 VectorAPI 可以精确地控制和利用现代 CPU 普遍存在的 SIMD (Single Instruction Multiple Data) 硬件单元,特定的应用可以获得数倍以上的性能提升。

02 Java 高性能计算现状

SIMD 计算单元在 X86 平台(非 X86 平台也普遍存在 SIMD)上从 MMX(Multi Media eXtension)时代,演进到当前的 AVX-512 (Advanced Vector Extensions)/AMX(Advanced Matrix Extensions)时代,SIMD 技术在多媒体处理,游戏娱乐,大数据处理和最近火热的 AI 领域都发挥了至关重要的作用。开发者可以利用 C/C++(intrinsic指令),汇编语言等语言工具显式的编写 SIMD 相关代码(称之为向量化编码)来利用 SIMD 单元;也可以利用编译器/解释器的自动向量化功能来进行。JVM(Java Virtual Machine)也具有自动向量化的能力。


在利用编译器/解释器的自动向量化功能的时候,虽然开发人员的负担较小,但由于这些工作都依赖于编译器/解释器的实现,很多时候无法达到预期的目的。而开发人员能做的却很有限,SIMD 硬件的性能往往不能充分发挥;而直接针对 SIMD 硬件编程,较老版本的 Java 却只能通过 JNI(Java Native Interface),调用使用 C/C++ 或者汇编语言实现的库来实现。JNI 的引入,将带来不容忽视的额外性能开销;同时混合编程模式也会增加系统管理维护的复杂度。Java VectorAPI (向量 API)的出现,给了 Java 开发者直接面向 SIMD 硬件的编程能力。使用 SIMD 硬件的途径:


自动向量化 调用本地语言库

直接针对 SIMD 单元编程

C/C++、汇编

等本地语言


 (Intrinsic/汇编)
Java 是(JNI) (VectorAPI)

03 VectorAPI 介绍

VectorAPI (Incubator, JEP 338, JEP:JDK Enhancement Proposals) 最初于 2018 年 4 月开始创建,在 OpenJDK16 作为孵化器项目(2020年10月)被引入。随着后续 OpenJDK 版本的升级,VectorAPI 也得到了同步升级:

  • OpenJDK 17 -> JEP 414,Second Incubator
  • OpenJDK 18 -> JEP 417,Third Incubator
  • OpenJDK 19 -> JEP 426,Fourth Incubator
  • OpenJDK 20 -> JEP 438,Fifth Incubator

每次 VectorAPI 的升级都会带来性能提升,更多功能和 Bugfix。VectorAPI 的编程使用的是纯 Java 代码,下面看一个简单例子

// 传统写法实现2个数组相加
void add (float[] A, float[] B, float[] C) { 
    for (int i = 0; i < C.length; i++) { 
        C[i] = A[i] + B[i]; 
    } 
} 
// 使用VectorAPI的2个数组相加
public class AddClass<S extends Vector.Shape<Vector<?, ?>>> { 
    private final FloatVector.FloatSpecies<S> spec; 
    AddClass (FloatVector.FloatSpecies<S> v) {spec = v; } 
    // vector routine for add  
    void add (float[] A, float[] B, float[] C) { 
        int i=0; 
        for (; i + spec.length() < C.length; i += spec.length()) { 
            FloatVector<S> av = spec.fromArray(A, i); 
            FloatVector<S> bv = spec.fromArray(B, i); 
            av.add (bv).intoArray(C, i); 
        } 
        // clean up loop 
        for (; i < a.length; i++) C[i] = A[i] + B[i]; 
    } 
}


可以看出,在使用 VectorAPI 后,在支持 AVX-512 的硬件平台上,一次加法可以处理 (512/32=16) 16 个浮点数;而传统加法一次只能处理一个浮点数。下面是一些 VectorAPI 的实际例子:

  • 高性能计算、AI、多媒体领域广泛使用的 BLAS (Basic Linear Algebra Subprograms,基本线性代数子程序),可以得到 2.2X~4.5X 的提升。

  • 图像处理 Sepia 过滤 ,最多得到 6 倍提升:

  • 数据库应用 2 倍以上提升:

由于 VectorAPI 是一个比较新的模块,更多利用 VectorAPI 的新项目正在开发中。

04 业界 Java 版本现状

在 Apache Parquet-mr 项目中,使用 VectorAPI 需要 JDK17 的支持。一方面 JDK17 是 Java 的 LTS (Long-Term Support) 版本,更为重要的是前一个 Java LTS 版本 JDK11 并不支持 VectorAPI。但是业界 JDK11 的使用比 JDK17 更为广泛,而在成熟的生产环境中升级 Java 版本是一件代价高昂的事情,这就造成了 VectorAPI 在业界推广使用的一个显而易见的巨大障碍。对此业界也做了不少努力和尝试,比如阿里巴巴在其内部使用的 AJDK上,已经加入了 VectorAPI 的支持,但是其实现和 OpenJDK 社区还是有差别,后续的升级维护不是一件容易的事情。因此阿里巴巴和英特尔开始了将 VectorAPI  (JEP 338)移植到 Dragonwell11 上的项目。这样既可以利用 VectorAPI 的强大功能,又保护了现在的投资,避免了升级 JDK 的风险

05 移植难点

  • 涉及代码量巨大

社区 JEP 338 涉及 336 文件修改,涉及代码行数 29 万行。而这些都是以 JDK16 为基准的和基于 JDK11 的 Dragonwell 相比,差异会更大。

  • 保持和上游 OpenJDK 的关联

而且一方面要让 Dragonwell11 能继续方便追踪上游 OpenJDK11 的修正增强,还要让 VectorAPI 也能较为方便跟踪上游 OpenJDK 后续 VectorAPI 的演进,对移植工作带来了不小挑战。

  • 性能要和上游 OpenJDK 接近

OpenJDK11 以后的版本的一些性能相关改动以及如何引入 Dragonwell11?

  • 稳定可靠的强需求

Dragonwell 需要支持现有的大量业务,稳定可靠是第一位的要求。


06 解决方案


针对海量的代码,阿里巴巴和英特尔都投入了大量资源,其中双方都包括了上游 OpenJDK 社区 VectorAPI 的关键贡献者,双方紧密合作,讨论方案,检查代码。在移植过程中,尽量保持 Dragonwell11 的原有结构,只涉及 VectorAPI 的部分才采用上游的实现。一些上游 JDK11 以后的改动,分析其实现,如果可以使用现有 Dragonwell11 的组件,就不引入额外的改动。这样把对 Dragonwell11 的影响降到最小。并且利用 OpenJDK 内建的测试集,完整覆盖移植后的 Dragonwell11,来保证移植的质量。

07 Dragonwell11 + VectorAPI

目前,VectorAPI 已经合并到 Dragonwell11 的主分支(master),且完全兼容 VectorAPI 1st Incubator (JEP 338),后续还会把 JEP 414、JEP 417、JEP 426、JEP 438 的功能移植到 Dragonwel11 上。


相关链接:

Alibaba Dragonwell:https://github.com/alibaba/dragonwell11

OpenJDK :https://github.com/openjdk/jdk


—— 完 ——

相关文章
|
2月前
|
Kubernetes Cloud Native Java
云原生之旅:从容器到微服务的演进之路Java 内存管理:垃圾收集器与性能调优
【8月更文挑战第30天】在数字化时代的浪潮中,企业如何乘风破浪?云原生技术提供了一个强有力的桨。本文将带你从容器技术的基石出发,探索微服务架构的奥秘,最终实现在云端自由翱翔的梦想。我们将一起见证代码如何转化为业务的翅膀,让你的应用在云海中高飞。
|
2月前
|
监控 Java 测试技术
Java并发编程最佳实践:设计高性能的多线程系统
Java并发编程最佳实践:设计高性能的多线程系统
52 1
|
2月前
|
存储 监控 Java
Java多线程优化:提高线程池性能的技巧与实践
Java多线程优化:提高线程池性能的技巧与实践
83 1
|
2月前
|
存储 缓存 Java
Java本地高性能缓存实践问题之如何定义Caffeine的缓存
Java本地高性能缓存实践问题之如何定义Caffeine的缓存
|
2天前
|
缓存 算法 Java
Java 实现的局域网管控软件的性能调优
局域网管控软件在企业网络管理中至关重要,但随着网络规模扩大和功能需求增加,其性能可能受影响。文章分析了数据处理效率低下、网络通信延迟和资源占用过高等性能瓶颈,并提出了使用缓存、优化算法、NIO库及合理管理线程池等调优措施,最终通过性能测试验证了优化效果,显著提升了软件性能。
12 1
|
1月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
307 37
|
14天前
|
缓存 Java 数据库连接
使用 NCache 将 Java 微服务扩展到极致性能
使用 NCache 将 Java 微服务扩展到极致性能
23 8
|
1月前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
1328 11
|
1月前
|
缓存 Java 应用服务中间件
Java虚拟线程探究与性能解析
本文主要介绍了阿里云在Java-虚拟-线程任务中的新进展和技术细节。
|
1月前
|
监控 算法 Java
深入理解Java中的垃圾回收机制在Java编程中,垃圾回收(Garbage Collection, GC)是一个核心概念,它自动管理内存,帮助开发者避免内存泄漏和溢出问题。本文将探讨Java中的垃圾回收机制,包括其基本原理、不同类型的垃圾收集器以及如何调优垃圾回收性能。通过深入浅出的方式,让读者对Java的垃圾回收有一个全面的认识。
本文详细介绍了Java中的垃圾回收机制,从基本原理到不同类型垃圾收集器的工作原理,再到实际调优策略。通过通俗易懂的语言和条理清晰的解释,帮助读者更好地理解和应用Java的垃圾回收技术,从而编写出更高效、稳定的Java应用程序。