了解 LLVM





5.00/5 (6投票s)
本文概述了 LLVM 及其在 oneAPI 及其编译器中的应用。
LLVM 是一个最初为 C 和 C++ 构建的免费开源编译器基础设施。虽然其名称最初代表“低级虚拟机”(Low Level Virtual Machine),但 LLVM 现在已经发展成为一种远不止处理虚拟机的技术。该名称不再是官方缩写。
LLVM 的核心组件是与语言无关的中间表示(IR)。这种 IR 作为编译器系统的中间层,并生成更低级的 IR。然后,低级 IR 被简化为针对目标机器进行优化的汇编语言代码。或者,它还可以进一步简化为运行时二进制机器代码的级别。
本文探讨了基于 LLVM 的编译器的优势及其跨架构能力,并介绍了几种英特尔基于 LLVM 的 oneAPI 编译器示例。
LLVM 的历史
LLVM 项目于 2000 年由 Vikram Adve 和 Chris Lattner 在伊利诺伊大学厄巴纳-香槟分校启动。它被设计成模块化的,能够快速适应不同的编译器前端和后端。
自成立以来,LLVM 已从一个以研究为导向的项目发展成为当今许多行业标准商业编译器的基础。该项目已在 Go、Haskell、OCaml、Rust、Scala、Nimrod、JavaScript、Objective-C、C#、Fortran 和 Python 等多种其他语言中实现。
LLVM 被广泛应用于各种系统,包括链接器、汇编器、调试器和编译器,例如英特尔 oneAPI 上提供的那些。英特尔以前的编译器基于 Open64 基础设施。然而,英特尔已经采纳了 LLVM,现在提供使用该基础设施的 C/C++ 和 Fortran 编译器。
基于 LLVM 的编译器的优势
基于 LLVM 的编译器在许多方面对开发人员和商业组织都很有价值。让我们考虑一些好处。
更短的构建时间
LLVM 是一个生产级别的编译器基础设施,为不同的编译器提供了一个框架。我们不必每次都从头开始编写相同的组件,而是可以使用 LLVM 社区已编写和测试过的组件来构建我们的 LLVM 编译器。这使我们能够将更多时间花在我们项目的独特方面,而花更少的时间来重写代码。
易于维护和优化
LLVM 编译器轻量级且易于维护。它们将代码编译成本机对象文件或虚拟机可以执行的字节码。一些编译器还输出中间汇编代码或生成二进制可执行文件。这些编译器专为内存有限且性能至关重要的嵌入式系统而设计。它们也成功地用于超级计算机,以优化大型工作负载的执行速度。
由于 LLVM 是一个模块化库,我们可以只使用我们需要的 LLVM 部分。我们可以挑选在我们的编译器中使用的组件和优化。我们还可以根据需要将自己的优化插入到管道中。
灵活性
LLVM 编译器足够灵活,可以支持具有低级(机器代码)和高级(人类可读代码)功能的编程语言。通过这种方式,我们可以在不从头开始创建自己的编译器的情况下创建自定义编程语言,以便在想要添加新功能或更改现有功能时使用。
我们可以轻松地为新语言和目标架构添加新的前端和后端。此外,我们可以使用 LLVM 编译器基础设施来构建测试和分析工具,而无需修改编译器本身。
可移植性
LLVM 被设计为可以针对其他编译器后端,这意味着我们可以使用它为我们选择的平台生成机器代码。它还为动态编程语言提供汇编器、反汇编器、链接器和即时(JIT)编译器等功能。通过允许我们的编译器针对 LLVM IR 代码而不是实际的机器代码,我们可以比直接从编译器的前端生成机器代码获得更好的可移植性。
由于该编译器可以在许多不同的平台上运行,因此我们可以轻松地将使用它开发的任何应用程序移植到新平台。
英特尔 oneAPI 编译器选项
我们可以使用不同的编译器来影响代码生成和优化。基于 LLVM 的 oneAPI 编译器有两个示例:Intel oneAPI DPC++/C++ Compiler 和 Intel Fortran Compiler (IFX)。
Intel oneAPI DPC++/C++ Compiler
oneAPI 的 Data Parallel C++ (DPC++) 是一个由英特尔主导的项目,它允许我们编写在不同计算系统上执行的程序,而无需进行耗时的大量代码更改。Intel oneAPI DPC++/C++ Compiler 是一个单一源解决方案,用于为 CPU、GPU、FPGA 和其他加速硬件编译数据并行 C++ 代码。该编译器支持 Windows 和 Linux 操作系统。它基于 LLVM 构建,使用 Clang 前端,支持 SYCL 2020 标准的 C++,并通过同一源文件支持 OpenCL 内核。
SYCL 是 Khronos Group 的一项开放标准。Khronos Group。它基于标准 C++ 为异构计算平台提供单源编程。
英特尔通过 DPC++ 实现 SYCL 规范(包含一些扩展)。DPC++ 编译器用于原型化 SYCL 2020 及其许多功能。这意味着 DPC++ 编译器是从事 SYCL 2020 项目的程序员的不错选择。英特尔使用 DPC++ 来支持英特尔 GPU、CPU 和 FPGA。
基于 Clang 前端 LLVM 技术的 DPC++/C++ Compiler 允许我们使用通用的编程标准编写适用于所有加速器平台的代码。这通过消除维护多个开发路径的需求来帮助降低开发成本。它还简化了代码在硬件平台之间的移植。它支持 OpenMP 5.0 和 5.1 TARGET 卸载到英特尔 GPU 目标。
该编译器包含三个编译器驱动程序 — icx、icpx 和 dpcpp — 以进一步简化为独特支持要求量身定制代码的过程。这些驱动程序分别用于编译和链接 C 程序、C++ 程序以及带有 SYCL 扩展的 C++ 程序。对于 Windows 系统,dcpcpp SYCL 扩展支持驱动程序具有略微不同的命名约定:dpcpp-cl。使用 dcpcpp SYCL 扩展进行编译可为未来的加速需求提供额外的灵活性。
Intel Fortran Compiler (IFX)
ifx 是一个 Fortran 编译器,它使用 LLVM 后端编译器技术,但它基于 Intel® Fortran Compiler Classic 前端和运行时库。它有一个基本模式,支持 Fortran 77、最高到 Fortran 95 的语言标准,以及 Fortran 2003 到 Fortran 2018 的大部分功能。它还支持 OpenMP 5.0/5.1 和 OpenMP 4.5 卸载功能和指令。
基于 LLVM 的编译器的跨架构能力
许多编译器针对的是单一架构,例如 NVIDIA GPU 的 NVCC。然而,LLVM 编译器基础设施的最新进展使得基于 LLVM 的编译器能够针对多个架构域。例如,Clang C 和 C++ 编译器使用 LLVM 框架为 CPU 生成可执行代码。Clang 还可以通过定位适当的运行时库为不同的 GPU 和 FPGA 生成可执行代码。
基于 LLVM 的编译器还通过使用 NVIDIA NVPTX 后端支持 GPU 和 FPGA 卸载。这些编译器有一个前端,将源代码解析为中间表示(IR),还有一个后端,可以为用户提供的各种架构生成机器代码。我们可以使用 Intel DPC++ Unified Shared Memory 等工具高效地共享资源,而不是为每个加速器使用独立的资源。
GPU 和 FPGA 卸载在多个英特尔 oneAPI 产品中默认启用
- Intel oneAPI HPC Toolkit
- Intel oneAPI Base Toolkit
- Intel AI Analytics Toolkit
Clang 编译器具有与 GNU Compiler Collection (GCC) 不同的前端,但它具有相同的 LLVM 后端。它使用与 GCC 工具链相同的代码生成工具链和优化通道。
我们可以使用一个编译器构建应用程序,然后将应用程序的某些部分卸载到 GPU 或 FPGA 上运行,具体取决于计算需求。这使我们能够以最小的努力利用更合适的专用计算核心。对于需要图形或 AI 加速器的应用程序,这是一种避免并行化这些平台所需的大量代码库修订的强大方法。
此外,我们还能够自动化本应需要大量手动工作的优化任务。我们可以快速地将应用程序扩展到多个设备,而无需聘请额外的员工或花费时间优化他们的代码。
最终想法
如果您正在开发涉及 XPU 的用例,或者正在将现有 GPU 和 FPGA 的代码迁移到新架构,LLVM 编译器应该是您策略的关键组成部分。基于 LLVM 的编译器提供更短的构建时间、灵活性、可移植性以及易于维护和优化。
Intel oneAPI 提供了一个标准的编程模型,以简化开发体验并实现跨各种架构的软件可移植性。
尝试oneAPI,以了解其跨架构功能的更多信息,并尝试将其用于加速架构。英特尔还提供 Data Parallel C++ 的培训,以帮助开发人员充分利用 oneAPI 的功能。