diff --git a/docs/en/gcc/_toc.yaml b/docs/en/gcc/_toc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5d91c7a31591fedc3cf5e71ffa1b97d51d35b3a8 --- /dev/null +++ b/docs/en/gcc/_toc.yaml @@ -0,0 +1,14 @@ +label: GCC User Guide +isManual: true +description: GCC for openEuler builds upon the open source GCC, with a primary focus on optimizing C, C++, and Fortran languages +sections: + - label: Kernel FDO User Guide + href: ./kernel_fdo_user_guide.md + - label: LTO User Guide + href: ./lto_user_guide.md + - label: GCC Basic Performance Optimization User Guide + href: ./gcc_basic_performance_optimization_user_guide.md + - label: Alternative GCC 14 User Guide + href: ./gcc_14_secondary_version_compilation_toolchain_user_guide.md + - label: PIN User Guide + href: ./pin_user_guide.md diff --git a/docs/en/gcc/gcc_14_secondary_version_compilation_toolchain_user_guide.md b/docs/en/gcc/gcc_14_secondary_version_compilation_toolchain_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..947bcbc6aed1624cdfb75fbdf15619b051fc230e --- /dev/null +++ b/docs/en/gcc/gcc_14_secondary_version_compilation_toolchain_user_guide.md @@ -0,0 +1,139 @@ +# Background + +## Overview + +OSs prioritize robustness by adopting time-tested, stable software versions rather than the latest releases. This strategy minimizes instability risks from version changes and maintains system stability throughout the LTS cycle. Consequently, openEuler has chosen GCC 12.3.1 as its baseline for the entire 24.03 LTS lifecycle. + +This decision, however, introduces challenges. Many hardware features rely on the foundational GCC toolchain, and using an older GCC version delays the activation of new features in OS releases. Additionally, some users prefer the latest compiler versions to unlock new capabilities, which often deliver performance gains over older versions. + +To enable diverse computational features and cater to varying user needs for hardware support, openEuler 24.09 introduces the openEuler GCC Toolset. This multi-version GCC compilation toolchain, tailored for openEuler, provides a secondary GCC version higher than the system primary version, offering users a more flexible and efficient compilation environment. With the openEuler GCC Toolset 14, users can seamlessly switch between GCC versions to leverage new hardware features and benefit from the latest GCC optimizations. + +## Solution Design + +### Compilation Toolchain Features + +The GCC compilation toolchain, developed and maintained by GNU, is a collection of open source tools designed to translate high-level language code into machine language. Beyond GCC itself, it includes a range of auxiliary tools and libraries, collectively forming a comprehensive compilation environment. + +1. GCC compiler (such as `gcc`, `g++`, and `gfortran`): + + - Role: The GCC compiler is the heart of the toolchain, handling preprocessing and compilation to transform source code into assembly or intermediate representation. For C++ code, `g++` acts as the C++ frontend, performing compilation and automatically linking C++ standard libraries. + +2. Binutils toolset: + + - Tools: including the linker (`ld`), assembler (`as`), object file viewer (`readelf`), symbol viewer (`nm`), object file format converter (`objcopy`), disassembler (`objdump`), and size viewer (`size`) + - Role: These tools support the compilation process by converting assembly to machine code, linking object files into executables, and inspecting file details. + +3. glibc library: + + - Role: The GNU C Library (glibc) is the standard C library for GNU and Linux systems, providing essential functions like `printf` and `malloc` required for compiling C programs. + +4. Other auxiliary tools: + + - Debugger (`gdb`): assists developers in debugging executables to identify and fix errors. + - Performance Analysis Tool (`gprof`): helps analyze and optimize program performance. + +### Toolchain Selection + +The software components in the toolchain significantly influence compilation results, with GCC, binutils, and glibc being the core elements. Since glibc, the C standard library, is tightly coupled with the OS kernel version, it remains unchanged. This toolchain includes only GCC and binutils to fulfill the needs of secondary version compilation. + +The latest GCC release, gcc-14.2.0, is selected for the openEuler GCC toolset. For binutils, while openEuler 24.09 defaults to version 2.41, the latest GCC 14 recommends binutils-2.42. Thus, binutils-2.42 is chosen for this toolchain. + +The openEuler GCC toolset incorporates gcc-14.2.0 and binutils-2.42 as the secondary version toolchain to ensure compilation environment stability and efficiency while minimizing complexity. This approach balances compilation quality and user experience. The toolchain GCC version will be updated to gcc-14.3.0 upon its release by the upstream community. + +### Architecture Design + +To differentiate from the default toolchain and prevent conflicts, this toolchain is named gcc-toolset-14. Its package names begin with the prefix `gcc-toolset-14-`, followed by the original toolchain package name. To avoid path overlap with the default **/usr** installation path, gcc-toolset-14 is installed in **/opt/openEuler/gcc-toolset-14/**. Additionally, to distinguish it from open source GCC and enable future integration of openEuler community features, the version of gcc-toolset-14-gcc is set to 14.2.1. + +The applications and libraries in gcc-toolset-14 coexist with the system default GCC version without replacing or overwriting it. They are not set as the default or preferred option. To simplify version switching and management, the scl-utils tool is introduced. Its usage and switching methods are outlined below. + +## Installation and Deployment + +### Software Requirements + +- OS: openEuler 24.09 + +### Hardware Requirements + +- AArch64 or X86_64 + +### Installation Methods + +Install the default GCC compiler, gcc-12.3.1, in **/usr**: + +```shell +yum install -y gcc gcc-c++ +``` + +Install the secondary version compilation toolchain, gcc-toolset-14, in **/opt/openEuler/gcc-toolset-14/root/usr/**: + +```shell +yum install -y gcc-toolset-14-gcc* +yum install -y gcc-toolset-14-binutils* +``` + +## Usage + +This solution uses the SCL (Software Collections) tool to manage different versions of the compilation toolchain. + +### SCL + +SCL is a vital Linux tool that enables users to install and use multiple versions of applications and runtime environments safely and conveniently, preventing system conflicts. + +Key benefits of SCL include: + +1. Multi-version coexistence: allows installing and using multiple versions of software libraries, tools, and runtime environments on the same system to meet diverse needs. +2. Avoiding system conflicts: isolates different software versions to prevent conflicts with the system default version. +3. Enhancing development efficiency: provides developers with the latest toolchains and runtime environments, improving productivity. + +### Version Switching Methods + +**Install SCL:** + +```shell +yum install scl-utils scl-utils-build +``` + +**Register gcc-toolset-14:** + +```shell +## Register gcc-toolset-14. +scl register /opt/openEuler/gcc-toolset-14/ + +## Deregister gcc-toolset-14. +scl deregister gcc-toolset-14 +``` + +Use `scl list-collections` to verify that gcc-toolset-14 is successfully registered. + +**Switch to gcc-toolset-14:** + +```shell +scl enable gcc-toolset-14 bash +``` + +This command launches a new bash shell session with tools from gcc-toolset-14, replacing the system defaults. In this session, there is no need to manually switch compiler versions or paths. To exit the gcc-toolset-14 environment, type `exit` to return to the system default version. + +SCL works by automatically setting environment variables for different tool versions. For details, check the **/opt/openEuler/gcc-toolset-14/enable** file, which contains all environment variable configurations for gcc-toolset-14. If SCL is unavailable, use the following methods to switch toolchain versions: + +```shell +## Option 1: Without SCL, use a script to switch the compilation toolchain. +source /opt/openEuler/gcc-toolset-14/enable + +## Option 2: With SCL, use SCL to switch the toolchain and activate the runtime environment. +scl enable gcc-toolset-14 bash +``` + +## Usage Constraints + +### Compilation Scenarios + +- **Primary version**: Use the system default gcc-12.3.1 for standard compilation and building. +- **Secondary version**: When the advanced features of GCC 14 are needed for application building, use SCL to switch the bash environment to the gcc-toolset-14 compilation environment. + +### GCC 14 Secondary Version Usage Instructions + +1. The openEuler GCC toolset 14 secondary compilation toolchain offers two usage methods: + 1) **Dynamic linking**: By default, the `-lstdc++` option is automatically included for dynamic linking. This links the system dynamic library **/usr/lib64/libstdc++.so.6** and the **libstdc++_nonshared.a** static library provided by the GCC 14 secondary version. This static library contains stable C++ features introduced in GCC 14 compared to GCC 12. + 2) **Static linking**: You can use the `-static` option for static linking, which links the full-feature **libstdc++.a** static library provided by the GCC 14 secondary version. The path to this library is **/opt/openEuler/gcc-toolset-14/root/usr/lib/gcc/aarch64-openEuler-linux/14/libstdc++.a**. + +2. By default, builds use dynamic linking, which links the **libstdc++_nonshared.a** static library. To ensure system compatibility, this library only includes officially standardized C++ features. Experimental features like `-fmodules-ts` and `-fmodule-header`, which are part of C++20 module capabilities, are not included in **libstdc++_nonshared.a**. If you need these features, you should use static linking to fully link the GCC 14 secondary version static library. diff --git a/docs/en/gcc/gcc_basic_performance_optimization_user_guide.md b/docs/en/gcc/gcc_basic_performance_optimization_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..e65f3458ee487eb261d7f254db1aeac3b8cb4946 --- /dev/null +++ b/docs/en/gcc/gcc_basic_performance_optimization_user_guide.md @@ -0,0 +1,185 @@ +# GCC Basic Performance Optimization User Guide + +## Introduction + +Compiler performance optimization plays a vital role in enhancing application development efficiency, runtime performance, and maintainability. It is a significant research area in computer science and a critical component of the software development process. GCC for openEuler extends its general compilation optimization capabilities by improving backend performance techniques, including instruction optimization, vectorization enhancements, prefetching improvements, and data flow analysis optimizations. + +## Installation and Deployment + +### Software Requirements + +OS: openEuler 24.09 + +### Hardware Requirements + +AArch64 architecture + +### Software Installation + +Install GCC and related components as required. For example, to install GCC: + +```shell +yum install gcc +``` + +## Usage + +### CRC Optimization + +#### Description + +Detects CRC software loop code and generates efficient hardware instructions. + +#### Usage + +Include the `-floop-crc` option during compilation. + +Note: The `-floop-crc` option must be used alongside `-O3 -march=armv8.1-a`. + +### If-Conversion Enhancement + +#### Description + +Improves If-Conversion optimization by leveraging additional registers to minimize conflicts. + +#### Usage + +This optimization is part of the RTL if-conversion process. Enable it using the following compilation options: + +`-fifcvt-allow-complicated-cmps` + +`--param=ifcvt-allow-register-renaming=[0,1,2]` (The value controls the optimization scope.) + +Note: This optimization requires the `-O2` optimization level and should be used with `--param=max-rtl-if-conversion-unpredictable-cost=48` and `--param=max-rtl-if-conversion-predictable-cost=48`. + +### Multiplication Calculation Optimization + +#### Description + +Optimizes Arm-related instruction merging to recognize 32-bit complex combinations of 64-bit integer multiplication logic and produce efficient 64-bit instructions. + +#### Usage + +Enable the optimization using the `-fuaddsub-overflow-match-all` and `-fif-conversion-gimple` options. + +Note: This optimization requires `-O3` or higher optimization levels. + +### cmlt Instruction Generation Optimization + +#### Description + +Generates `cmlt` instructions for specific arithmetic operations, reducing the instruction count. + +#### Usage + +Enable the optimization using the `-mcmlt-arith` option. + +Note: This optimization requires `-O3` or higher optimization levels. + +### Vectorization Optimization Enhancement + +#### Description + +Identifies and simplifies redundant instructions generated during vectorization, enabling shorter loops to undergo vectorization. + +#### Usage + +Enable the optimization using the parameter `--param=vect-alias-flexible-segment-len=1` (default is 0). + +Note: This optimization requires `-O3` or higher optimization levels. + +### Combined Optimization of min max and uzp1/uzp2 Instructions + +#### Description + +Identifies opportunities to optimize `min max` and `uzp1/uzp2` instructions together, reducing the instruction count to enhance performance. + +#### Usage + +Enable `min max` optimization with the `-fconvert-minmax` option. The `uzp1/uzp2` instruction optimization is automatically enabled at `-O3` or higher levels. + +Note: This optimization requires `-O3` or higher optimization levels. + +### ldp/stp Optimization + +#### Description + +Detects poorly performing `ldp/stp` instructions and splits them into two separate `ldr` and `str` instructions. + +#### Usage + +Enable the optimization using the `-fsplit-ldp-stp` option. Control the search range with the parameter `--param=param-ldp-dependency-search-range=[1,32]` (default is 16). + +Note: This optimization requires `-O1` or higher optimization levels. + +### AES Instruction Optimization + +#### Description + +Identifies AES software algorithm instruction sequences and replaces them with hardware instructions for acceleration. + +#### Usage + +Enable the optimization using the `-fcrypto-accel-aes` option. + +Note: This optimization requires `-O3` or higher optimization levels. + +### Indirect Call Optimization + +#### Description + +Analyzes and optimizes indirect calls in the program, converting them into direct calls where possible. + +#### Usage + +Enable the optimization using the `-ficp -ficp-speculatively` options. + +Note: This optimization must be used with `-O2 -flto -flto-partition=one`. + +### IPA-prefetch + +#### Description + +Detects indirect memory accesses in loops and inserts prefetch instructions to minimize latency. + +#### Usage + +Enable the optimization using the `-fipa-prefetch -fipa-ic` options. + +Note: This optimization must be used with `-O3 -flto`. + +### -fipa-struct-reorg + +#### Description + +Optimizes memory layout by reorganizing the arrangement of structure members to improve cache hit rates. + +#### Usage + +Add the options `-O3 -flto -flto-partition=one -fipa-struct-reorg` to enable the optimization. + +Note: The `-fipa-struct-reorg` option requires `-O3 -flto -flto-partition=one` to be enabled globally. + +### -fipa-reorder-fields + +#### Description + +Optimizes memory layout by reordering structure members from largest to smallest, reducing padding and improving cache hit rates. + +#### Usage + +Add the options `-O3 -flto -flto-partition=one -fipa-reorder-fields` to enable the optimization. + +Note: The `-fipa-reorder-fields` option requires `-O3 -flto -flto-partition=one` to be enabled globally. + +### -ftree-slp-transpose-vectorize + +#### Description + +Enhances data flow analysis for loops with consecutive memory reads by inserting temporary arrays during loop splitting. During SLP vectorization, it introduces transposition analysis for `grouped_stores`. + +#### Usage + +Add the options `-O3 -ftree-slp-transpose-vectorize` to enable the optimization. + +Note: The `-ftree-slp-transpose-vectorize` option requires `-O3` to be enabled. diff --git a/docs/en/gcc/kernel_fdo_user_guide.md b/docs/en/gcc/kernel_fdo_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..02c9ec2b151b0e06e05168bd6de78374be9acfd8 --- /dev/null +++ b/docs/en/gcc/kernel_fdo_user_guide.md @@ -0,0 +1,69 @@ +# Kernel FDO User Guide + +## Overview + +The feedback-directed optimization (FDO) of the kernel allows users to build optimized kernels for different applications to improve the application performance in single-application scenarios. In addition, FDO is integrated GCC for openEuler, and A-FOT provides automatic optimization, enabling users to easily enable FDO. + +## Installation and Deployment + +### Software Requirements + +* OS: openEuler 23.09 + +### Hardware Requirements + +* Architecture: AArch64 or x86_64 + +### Software Installation + +#### Downloading the Kernel Source Code + +Download the kernel source code, A-FOT, and dependency packages. + +```shell +yum install -y kernel-source A-FOT make gcc flex bison elfutils-libelf-devel diffutils openssl-devel dwarves +``` + +Copy the kernel source code. + +```shell +cp -r /usr/src/linux-6.4.0-8.0.0.16.oe2309.aarch64 . +``` + +**Note: Change the version number as required.** + +## Usage + +You can use A-FOT to enable kernel FDO and obtain the optimized kernel by specifying **opt_mode** as **Auto_kernel_PGO**. Other configuration items can be specified on the CLI, for example, `./a-fot --pgo_phase 1`. `-s` and `-n` options can be specified on CLI only. Options related to kernel FDO are as follows. + +| No.| Option (Configuration File)| Description | Default Value | +| ---- | -------------------- | ------------------------------------------------------------ | ------------------------ | +| 1 | config_file | Path of the configuration file. User configurations are read from this file. | ${afot_path}/a-fot.ini | +| 2 | opt_mode | Optimization mode to be executed by the tool. The value can be **AutoFDO**, **AutoPrefetch**, **AutoBOLT**, or **Auto_kernel_PGO**.| AutoPrefetch | +| 3 | pgo_mode | Kernel FDO mode, which can be **arc** (GCOV, using only the arc profile) or **all** (full PGO, using the arc and value profiles). | all | +| 4 | pgo_phase | FDO execution phase. The value can be **1** (kernel instrumentation phase) or **2** (data collection and kernel optimization phase). | 1 | +| 5 | kernel_src | Kernel source code directory. If this option is not specified, the tool automatically downloads the source code. | None (optional) | +| 6 | kernel_name | File name of the kernel build. The tool will add the **-pgoing** or **-pgoed** suffix depending on the phase. | kernel | +| 7 | work_path | Script working directory, which is used to store log files, wrappers, and profiles. | **/opt** (**/tmp** cannot be used.)| +| 8 | run_script | Application execution script. The user needs to write the script, which will be used by the tool to execute the target application.| /root/run.sh | +| 9 | gcc_path | GCC path. | /usr | +| 10 | -s | Silent mode. The tool automatically reboots and switches the kernel to execute the second phase. | None | +| 11 | -n | The tool is not used to compile the kernel. This option applies to the scenario where the execution environment and kernel compilation environment are different. | None | + +After configuring the compilation options, run the following command to use A-FOT to automatically optimize the kernel: + +```shell +a-fot --config_file ./a-fot.ini -s +``` + +**Note: The `-s` option instructs A-FOT to automatically reboot into the compiled kernel. If you do not want the tool to automatically perform this sensitive operation, omit this option. However, you need to manually reboot and perform the second phase (`--pgo_phase 2`).** + +**Note: All paths must be absolute paths.** + +**Note: The kernel of openEuler 23.09 does not support full PGO. Change the value of pgo_mode to arc.** + +## Compatibility + +This section describes the compatibility issues in some special scenarios. This project is in continuous iteration and issues will be fixed as soon as possible. Developers are welcome to join this project. + +* The kernel of openEuler 23.09 does not support full PGO. Change the value of pgo_mode to arc. diff --git a/docs/en/gcc/lto_user_guide.md b/docs/en/gcc/lto_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..cd188c1ca5f8c0e3c025f8b6b0562048ed0e926a --- /dev/null +++ b/docs/en/gcc/lto_user_guide.md @@ -0,0 +1,25 @@ +# Introduction to Link-Time Optimization + +In traditional compilation, GCC compiles and optimizes individual source files (compilation units) to generate .o object files containing assembly code. The linker then processes these `.o` files, resolving symbol tables and performing relocations to create the final executable. However, the linker, which has access to cross-file function call information, operates on assembly code and cannot perform compilation optimizations. Conversely, the compilation stage capable of optimizations lacks global cross-file information. While this approach improves efficiency by recompiling only modified units, it misses many cross-file optimization opportunities. + +Link-Time Optimization (LTO) addresses this limitation by enabling optimizations during the linking phase, leveraging cross-compilation-unit call information. To achieve this, LTO preserves the Intermediate Representation (IR) required for optimizations until linking. During linking, the linker invokes the LTO plugin to perform whole-program analysis, make better optimization decisions, and generate more efficient IR. This optimized IR is then converted into object files with assembly code, and the linker completes the standard linking process. + +# Enabling LTO in Version Builds + +## Background + +Many international communities have adopted LTO in their version builds to achieve better performance and smaller binary sizes. LTO is emerging as a key area for exploring compilation optimization opportunities. Starting with version 24.09, openEuler will introduce LTO in its version builds. + +## Solution + +To enable LTO during package builds, we will add `-flto -ffat-lto-objects` to the global compilation options in the macros of **openEuler-rpm-config**. The `-flto` flag enables Link-Time Optimization, while `-ffat-lto-objects` generates fat object files containing both LTO object information and the assembly information required for regular linking. During the build process, LTO object information is used for optimizations. However, since LTO object files are not compatible across GCC versions, we remove the LTO-related fields from `.o/.a` files before packaging them into `.rpm` files, retaining only the assembly code needed for regular linking. This ensures that static libraries remain unaffected. + +## Scope of Enablement + +Due to the significant differences between LTO and traditional compilation workflows, and to minimize the impact on version quality, LTO is currently enabled for only 500+ packages. The list of these packages is available in **/usr/lib/rpm/%{_vendor}/lto_white_list**. These whitelisted applications have been successfully built and passed their test suites with LTO enabled. The LTO compilation options (`-flto -ffat-lto-objects`) are applied only when building whitelisted applications; otherwise, they are omitted. + +In future innovation releases, we will work with application maintainers to expand the scope of LTO enablement. + +## Notes + +The current hot-patching mechanism is incompatible with LTO, causing hot patches to fail when LTO is enabled. We have agreed with the hot-patching team on a solution, which will be implemented in future releases. diff --git a/docs/en/gcc/pin_user_guide.md b/docs/en/gcc/pin_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..750526f34c29f74ac0ee266ec78a0bee058801f1 --- /dev/null +++ b/docs/en/gcc/pin_user_guide.md @@ -0,0 +1,134 @@ +# Installation and Deployment + +## Software + +* OS: openEuler 23.03 + +## Hardware + +* x86_64 +* Arm + +## Preparing the Environment + +* Install the openEuler operating system. For details, see the [*openEuler Installation Guide*](https://docs.openeuler.openatom.cn/en/docs/24.03_LTS_SP2/server/installation_upgrade/installation/installation_on_servers.html). + +### Install the dependency + +#### Installing the Software on Which the PIN GCC Client Depends + +```shell +yum install -y grpc +yum install -y grpc-devel +yum install -y grpc-plugins +yum install -y protobuf-devel +yum install -y jsoncpp +yum install -y jsoncpp-devel +yum install -y gcc-plugin-devel +yum install -y llvm-mlir +yum install -y llvm-mlir-devel +yum install -y llvm-devel +``` + +#### Installing the Software on Which the PIN Server Depends + +```shell +yum install -y grpc +yum install -y grpc-devel +yum install -y grpc-plugins +yum install -y protobuf-devel +yum install -y jsoncpp +yum install -y jsoncpp-devel +yum install -y llvm-mlir +yum install -y llvm-mlir-devel +yum install -y llvm-devel +``` + +## Installing PIN + +### rpmbuild + +#### Building the PIN GCC Client + +```shell +git clone https://gitee.com/src-openeuler/pin-gcc-client.git +cd pin-gcc-client +mkdir -p ~/rpmbuild/SOURCES +cp *.path pin-gcc-client.tar.gz ~/rpmbuild/SOURCES +rpmbuild -ba pin-gcc-client.spec +cd ~/rpmbuild/RPMS +rpm -ivh pin-gcc-client.rpm +``` + +#### Building the PIN Server + +```shell +git clone https://gitee.com/src-openeuler/pin-server.git +cd pin-server +mkdir -p ~/rpmbuild/SOURCES +cp *.path pin-server.tar.gz ~/rpmbuild/SOURCES +rpmbuild -ba pin-server.spec +cd ~/rpmbuild/RPMS +rpm -ivh pin-server.rpm +``` + +### Build + +#### Building the PIN GCC Client + +```shell +git clone https://gitee.com/openeuler/pin-gcc-client.git +cd pin-gcc-client +mkdir build +cd build +cmake ../ -DMLIR_DIR=${MLIR_PATH} -DLLVM_DIR=${LLVM_PATH} +make +``` + +#### Building the PIN Server + +```shell +git clone https://gitee.com/openeuler/pin-server.git +cd pin-server +mkdir build +cd build +cmake ../ -DMLIR_DIR=${MLIR_PATH} -DLLVM_DIR=${LLVM_PATH} +make +``` + +# Usage + +You can use `-fplugin` and `-fplugin-arg-libpin_xxx` to enable the Plug-IN (PIN) tool. +Command: + +```shell +$(TARGET): $(OBJS) + $(CXX) -fplugin=${CLIENT_PATH}/build/libpin_gcc_client.so \ + -fplugin-arg-libpin_gcc_client-server_path=${SERVER_PATH}/build/pin_server \ + -fplugin-arg-libpin_gcc_client-log_level="1" \ + -fplugin-arg-libpin_gcc_client-arg1="xxx" +``` + +You can use the `${INSTALL_PATH}/bin/pin-gcc-client.json` file to configure PIN. The configuration options are as follows: + +`path`: path of the executable file of the PIN server. + +`sha256file`: path of the PIN verification file `xxx.sha256`. + +`timeout`: timeout interval for cross-process communication, in milliseconds. + +Compile options: + +`-fplugin`: path of the .so file of the PIN client. + +`-fplugin-arg-libpin_gcc_client-server_path`: path of the executable program of the PIN server. + +`-fplugin-arg-libpin_gcc_client-log_level`: default log level. The value ranges from `0` to `3`. The default value is `1`. + +`-fplugin-arg-libpin_gcc_client-argN`: other parameters that can be specified as required. `argN` indicates the argument required by PIN. + +# Compatibility + +This section describes the compatibility issues in some special scenarios. This project is in continuous iteration and will be fixed as soon as possible. Developers are welcome to join this project. + +* When PIN is enabled in the `-flto` phase, multi-process compilation using `make -j` is not supported. You are advised to use `make -j1` for compilation. diff --git a/docs/zh/bisheng_autotuner/_toc.yaml b/docs/zh/bisheng_autotuner/_toc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c39e06ee9986808f82d52067507fbb62f04c4318 --- /dev/null +++ b/docs/zh/bisheng_autotuner/_toc.yaml @@ -0,0 +1,6 @@ +label: BiSheng-Autotuner用户指南 +isManual: true +description: BiSheng-Autotuner 是一个自动编译调优工具,与支持调优的编译器(如 LLVM for openEuler、GCC for openEuler)配合使用 +sections: + - label: BiSheng-Autotuner用户指南 + href: ./bisheng_autotuner_user_guide.md \ No newline at end of file diff --git a/docs/zh/bisheng_autotuner/bisheng_autotuner_user_guide.md b/docs/zh/bisheng_autotuner/bisheng_autotuner_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..b5d2c33ed474790c243149e8bb1cb754fa3e48ad --- /dev/null +++ b/docs/zh/bisheng_autotuner/bisheng_autotuner_user_guide.md @@ -0,0 +1,227 @@ +# BiSheng-Autotuner 使用手册 + +## BiSheng-Autotuner 介绍 + +[BiSheng-Autotuner](https://gitee.com/openeuler/BiSheng-Autotuner) 是一个基于 BiSheng-opentuner 的命令行工具,与支持调优的编译器(如 LLVM for openEuler、GCC for openEuler)配合使用。它负责生成搜索空间、操作参数并驱动整个调优过程。 + +[BiSheng-opentuner](https://github.com/Huawei-CPLLab/bisheng-opentuner) 是一个开源框架,用于构建特定领域的、多目标程序的自动调优器。 + +本文主要介绍基于 LLVM for openEuler 的自动调优编译流程,基于 GCC for openEuler 的自动调优请参考[AI4C 使用流程](https://gitee.com/openeuler/AI4C)。 + +## BiSheng-Autotuner 调优流程 + +调优流程(如图1所示)由两个阶段组成:初始编译阶段(initial compilation)和调优阶段(tuning process)。 + +![图1 BiSheng-Autotuner调优流程](figures/image1.png) + +图1 BiSheng-Autotuner调优流程 + +### 初始编译阶段 + +初始编译阶段发生在调优开始之前,BiSheng-Autotuner 首先会让编译器对目标程序代码做一次编译,在编译的过程中,编译器会生成一些包含所有可调优结构的 YAML 文件,告诉开发者在这个目标程序中哪些结构可以用来调优,比如模块(module)、函数(function)、循环(loop)。例如,循环展开是编译器中最常见的优化方法之一,它通过多次复制循环体代码,达到增大指令调度空间、减少循环分支指令开销的优化效果。若以循环展开次数(unroll factor)为对象进行调优,编译器会在 YAML 文件中生成所有可被循环展开的循环作为可调优结构。 + +### 调优阶段 + +当可调优结构顺利生成之后,调优阶段便会开始: + +1. BiSheng-Autotuner 首先读取生成好的可调优结构的 YAML 文件,从而产生对应的搜索空间,也就是生成针对每个可调优代码结构的具体的参数和范围。 + +2. 调优阶段会根据设定的搜索算法尝试一组参数的值,生成一个 YAML 格式的编译配置文件(compilation config),从而让编译器编译目标程序代码产生二进制文件。 + +3. 最后 BiSheng-Autotuner 将编译好的文件以开发者定义的方式运行并取得性能信息作为反馈。 + +4. 经过一定数量的迭代之后,BiSheng-Autotuner 将找出最终的最优配置,生成最优编译配置文件,以 YAML 的形式储存。 + +## BiSheng-Autotuner 使用 + +### 环境要求 + +必选: + +- 操作系统:openEuler 24.03 LTS 系列、openEuler 25.03 及高于 openEuler 25.03 的版本 + +- 架构:AArch64、x86_64 + +- Python 3.11.x + +- SQLite 3.0 + +可选: + +- LibYAML:推荐安装,可提升 BiSheng-Autotuner 文件解析速度 + +### BiSheng-Autotuner 获取 + +若开发者使用最新的 openEuler 系统,可以直接安装 `BiSheng-Autotuner` 和 `clang` 软件包。 + +```shell +yum install -y BiSheng-Autotuner +yum install -y clang +``` + +若需源码构建 `BiSheng-Autotuner`,可以参考以下步骤。 + +1. 安装 [BiSheng-opentuner](https://gitee.com/src-openeuler/BiSheng-opentuner/) + + ```shell + yum install -y BiSheng-opentuner + ``` + +2. 克隆并安装 [BiSheng-Autotuner](https://gitee.com/openeuler/BiSheng-Autotuner/) + + ```shell + cd BiSheng-Autotuner + ./dev_install.sh + ``` + +### BiSheng-Autotuner 运行 + +本文将以 coremark 为示例展示如何运行自动调优,coremark 源码请从 [github 社区](https://github.com/eembc/coremark)获取。更多 llvm-autotune 的详细用法,请参阅[帮助信息](#帮助信息)章节。以下为以 20 次迭代调优 coremark 的脚本示例: + +```bash +export AUTOTUNE_DATADIR=/tmp/autotuner_data/ +CompileCommand="clang -O2 -o coremark core_list_join.c core_main.c core_matrix.c core_state.c core_util.c posix/core_portme.c -DPERFORMANCE_RUN=1 -DITERATIONS=300000 -I. -Iposix -g -DFLAGS_STR=\"\"" + +$CompileCommand -fautotune-generate; +llvm-autotune minimize; +for i in $(seq 20) +do + $CompileCommand -fautotune ; + time=`{ /usr/bin/time -p ./coremark 0x0 0x0 0x66 300000; } 2>&1 | grep "real" | awk '{print $2}'`; + echo "iteration: " $i "cost time:" $time; + llvm-autotune feedback $time; +done +llvm-autotune finalize; +``` + +以下为分步说明: + +1. 配置环境变量 + + 使用环境变量 `AUTOTUNE_DATADIR` 指定调优相关的数据的存放位置(指定目录需要为空)。 + + ```shell + export AUTOTUNE_DATADIR=/tmp/autotuner_data/ + ``` + +2. 初始编译步骤 + + 添加编译器选项 `-fautotune-generate`,编译生成可调优代码结构。 + + ```shell + cd examples/coremark/ + clang -O2 -o coremark core_list_join.c core_main.c core_matrix.c core_state.c core_util.c posix/core_portme.c -DPERFORMANCE_RUN=1 -DITERATIONS=300000 -I. -Iposix -g -DFLAGS_STR=\"\" -fautotune-generate + ``` + + > [!WARNING]注意 + > 建议仅将此选项应用于需要重点调优的热点代码文件。若应用的代码文件过多(超过 500 个文件),则会生成数量庞大的可调优代码结构的文件,进而可能导致步骤3的初始化时间长(可长达数分钟),以及巨大的搜索空间导致的调优效果不显著、收敛时间长等问题。 + +3. 初始化调优 + + 运行 `llvm-autotune` 命令,初始化调优任务。生成最初的编译配置供下一次编译使用。 + + ```shell + llvm-autotune minimize + ``` + + `minimize` 表示调优目标,旨在最小化指标(例如程序运行时间)。也可使用 `maximize`,旨在最大化指标(例如程序吞吐量)。 + +4. 调优编译步骤 + + 添加毕昇编译器选项 `-fautotune`,读取当前 `AUTOTUNE_DATADIR` 配置并编译。 + + ```shell + clang -O2 -o coremark core_list_join.c core_main.c core_matrix.c core_state.c core_util.c posix/core_portme.c -DPERFORMANCE_RUN=1 -DITERATIONS=300000 -I. -Iposix -g -DFLAGS_STR=\"\" -fautotune + ``` + +5. 性能反馈 + + 开发者运行程序,并根据自身需求获取性能数字,使用 `llvm-autotune feedback` 反馈。如果开发者想以 coremark 运行时间为指标进行调优,可以采用如下方式: + + ```shell + time -p ./coremark 0x0 0x0 0x66 300000 2>&1 1>/dev/null | grep real | awk '{print $2}' + # 返回实际执行时间 31.09 + ``` + + ```shell + llvm-autotune feedback 31.09 + ``` + + > [!WARNING]注意 + > 建议在使用 `llvm-autotune feedback` 之前,先验证步骤 4 编译是否正常以及编译好的程序是否运行正确。若出现编译或者运行异常的情况,请输入相应调优目标的最差值(例如,调优目标为 minimize,可输入 `llvm-autotune feedback 9999`;maximize 可输入 0 或者 -9999)。 + > + > 若输入的性能反馈不正确,可能会影响最终调优的结果。 + +6. 调优迭代 + + 根据开发者设定的迭代次数,重复4和5进行调优迭代。 + +7. 结束调优 + + 进行多次迭代后,开发者可选择终止调优,并保存最优的配置文件。配置文件会被保存在环境变量 `AUTOTUNE_DATADIR` 指定的目录下。 + + ```shell + llvm-autotune finalize + ``` + +8. 最终编译 + + 使用步骤7得到最优配置文件,进行最后编译。在环境变量未改变的情况下,可直接使用 `-fautotune` 选项: + + ```shell + clang -O2 -o coremark core_list_join.c core_main.c core_matrix.c core_state.c core_util.c posix/core_portme.c -DPERFORMANCE_RUN=1 -DITERATIONS=300000 -I. -Iposix -g -DFLAGS_STR=\"\" -fautotune + ``` + + 或者使用 `-mllvm -auto-tuning-input=` 直接指向配置文件。 + + ```shell + clang -O2 -o coremark core_list_join.c core_main.c core_matrix.c core_state.c core_util.c posix/core_portme.c -DPERFORMANCE_RUN=1 -DITERATIONS=300000 -I. -Iposix -g -DFLAGS_STR=\"\" -mllvm -auto-tuning-input=/tmp/autotuner_data/config.yaml + ``` + +### 帮助信息 + +llvm-autotune 执行格式如下所示: + +```shell +llvm-autotune [-h] {minimize,maximize,feedback,dump,finalize} +``` + +可选指令: + +- `minimize`:初始化调优并生成初始的编译器配置文件,旨在最小化指标(例如运行时间)。 + +- `maximize`:初始化调优并生成初始的编译器配置文件,旨在最大程度地提高指标(例如吞吐量)。 + +- `feedback`:反馈性能调优结果并生成新的编译器配置。 + +- `dump`:生成当前的最优配置,而不终止调优(可继续执行 `feedback`)。 + +- `finalize`:终止调优,并生成最佳的编译器配置(不可再执行 `feedback`)。 + +### 编译器相关选项 + +llvm-autotune 需要与 LLVM 编译器选项 `-fautotune-generate` 和 `-fautotune` 配合使用。 + +- `-fautotune-generate`: + + - 在 `autotune_datadir` 目录下生成可调优的代码结构列表,此默认目录可由环境变量 `AUTOTUNE_DATADIR` 改写。 + + - 作为调优准备工作的第一步,通常需要在 `llvm-autotune minimize/maximize` 命令执行前使用。 + + - 此选项还可以赋值来改变调优的颗粒度(可选值为`Other`、`Function`、`Loop`、`CallSite`、`MachineBasicBlock`、`Switch`、`LLVMParam`、`ProgramParam`,其中 `LLVMParam` 和 `ProgramParam` 对应粗粒度选项调优)。例如 `-fautotune-generate=Loop` 会开启类型仅为循环的可调优代码结构,每个循环在调优过程中会被赋予不同的参数值;而 `Other` 表示全局,生成的可调优代码结构对应每个编译单元(代码文件)。 + + - `-fautotune-generate`默认等效于`-fautotune-generate=Function,Loop,CallSite`。通常建议使用默认值。 + + - 若要启用选项调优(`LLVMParam`和`ProgramParam`),需要为 llvm-autotune 指定拓展搜索空间,默认的搜索空间不包含预设调优选项。 + + ```shell + llvm-autotune minimize --search-space /usr/lib64/python/site-packages/autotuner/search_space_config/extended_search_space.yaml + ``` + + `site-packages`目录可以通过 `pip show autotuner` 指令找到。 + +- `-fautotune`: + + - 使用`autotune_datadir`下的编译器配置进行调优编译(此默认目录可由环境变量`AUTOTUNE_DATADIR`改写)。 + + - 通常在调优迭代过程中,`llvm-autotune minimize/maximize/feedback` 命令之后使用。 diff --git a/docs/zh/bisheng_autotuner/figures/image1.png b/docs/zh/bisheng_autotuner/figures/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..10e002c1402574e3e5b1f9d4f050efb4f439c22e Binary files /dev/null and b/docs/zh/bisheng_autotuner/figures/image1.png differ diff --git a/docs/zh/gcc/_toc.yaml b/docs/zh/gcc/_toc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..653e1cf77faed565d2f9944862094f7848b2fbe2 --- /dev/null +++ b/docs/zh/gcc/_toc.yaml @@ -0,0 +1,18 @@ +label: GCC用户指南 +isManual: true +description: GCC for openEuler 编译器基于开源 GCC 开发,聚焦于C、C++、Fortran语言的优化 +sections: + - label: 内核反馈优化特性 + href: ./kernel_fdo_user_guide.md + - label: 链接时优化特性 + href: ./lto_user_guide.md + - label: GCC优化特性 + href: ./gcc_optimization_user_guide.md + - label: GCC14副版本编译工具链 + href: ./gcc_14_secondary_version_compilation_toolchain_user_guide.md + - label: GCC插件框架特性 + href: ./pin_user_guide.md + - label: 编译时间优化特性 + href: ./compile_time_optimization_user_guide.md + - label: 动态反馈优化框架 + href: ./dfot_user_guide.md diff --git a/docs/zh/gcc/compile_time_optimization_user_guide.md b/docs/zh/gcc/compile_time_optimization_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..afa3abf80faab35ca6a500b559027a9b4d1dec0e --- /dev/null +++ b/docs/zh/gcc/compile_time_optimization_user_guide.md @@ -0,0 +1,36 @@ +# 背景 + +为了提升openEuler软件包的编译效率,从而进一步提升门禁和开发者开发效率,我们在2503版本使用了打开PGO(Profile Guided Optimization)、LTO(Link Time Optimization)编译的GCC结合mold(A Modern Linker)链接器来缩短软件包中C/C++库的编译时间。 + +# 方案 + +## 优化技术原理 + +Mold:是一种对比其他链接器(ld、gold、lld)链接效率更高的开源链接器,其通过更高效的Identical Comdat Folding(ICF)算法、更好的并行编程,更高效的多线程库等技术来提升链接的效率,具体可参考:。 + +PGO:利用程序运行时的剖析信息来指导编译优化,以提高程序的性能,运行时的剖析信息包括函数调用频率,分支走向等。 + +LTO:链接时优化,可以进行更多的跨模块的优化,消除模块之间的冗余代码和不必要的函数调用,提升GCC编译其他应用时候执行效率。 + +## 使能方式 + +在GCC的编译过程取消了`--disable-bootstrap`,同时添加了`BUILD_CONFIG=bootstrap-lto profiledbootstrap`来打开PGO和LTO去编译GCC。 + +在openEuler-rpm-config的macro中我们通过检查软件包名字是否在白名单中来给LDFLAGS添加`-fuse-ld=mold`,使得软件包可使用mold进行编译。 + +## 使能范围 + +打开了PGO、LTO编译的GCC在2503版本上默认使能。 + +由于mold链接器本身存在一定的功能欠缺(对kernel的不支持,对linker script支持不完善)我们在2503上使用[白名单](https://gitee.com/src-openeuler/openEuler-rpm-config/blob/openEuler-25.03/0002-Enable-mold-links-through-whitelist.patch#L49)的方式使能mold。 + +同时我们提供了更加灵活的链接器配置方式,各软件包可以在spec内覆写`_ld_use`变量来切换链接器,如: + +- `%define _ld_use %{nil}` 取消因为软件包在白名单中所添加的mold选项。 + +- `%define _ld_use -fuse-ld=xxx` 切换不同的链接器,注意当定义多个`-fuse-ld`选项时编译器会取最后一个配置项。 + +# 注意事项 + +1. 只有在构建环境上存在mold时,白名单内的软件包才会启用mold链接。 +2. 当启用mold链接的时候需在GCC 12版本及以上进行构建。 diff --git a/docs/zh/gcc/dfot_user_guide.md b/docs/zh/gcc/dfot_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..2e731c0c7ba5c6229694b4d0318f8e6490ca377d --- /dev/null +++ b/docs/zh/gcc/dfot_user_guide.md @@ -0,0 +1,98 @@ +# 动态反馈优化框架 + +## 介绍 + +D-FOT是动态反馈优化框架(**D**ynamic **F**eedback-oirected **O**ptimization **T**ool),目标是实现应用全自动、无感知使能反馈优化特性,全面提高反馈优化特性的易用性和性能表现。 +本框架计划实现两类动态优化特性:启动时优化和运行时优化,当前已实现基于oeAware在线调优框架的启动时优化功能。 +启动时优化:应用运行时自动执行采样和反馈优化,完成优化后自动接管下一次启动,不需要用户修改启动流程,应用重启后自动拉起优化版本。 +运行时优化:应用运行时自动执行采样和反馈优化,不需要用户操作重启,整个过程无用户介入,仅少量中断后即可使能优化版本。 + +## 软件架构说明 + +本框架包含以下几个模块: + +- 基于libkperf的采样数据处理 +- 基于sysboost的启动接管和二进制优化特性使能 +- 基于llvm-bolt的二进制反馈优化 +- oeAware调优插件dfot_tuner_sysboost实现 + +## 依赖项 + +系统OS要求:当前支持openEuler-22.03-LTS-SP4、openEuler-25.03。 + +以下依赖组件均可通过yum安装。 + +| 组件 | 代码仓 | 说明 | +| --------------- | ---------------- | ----------- | +| oeAware-manager | [https://gitee.com/openeuler/oeAware-manager](https://gitee.com/openeuler/oeAware-manager) | 业务在线无感调优框架 | +| libkperf | [https://gitee.com/openeuler/libkperf](https://gitee.com/openeuler/libkperf) | 轻量级全内存化采集工具 | +| sysboost | [https://gitee.com/openeuler/sysboost](https://gitee.com/openeuler/sysboost) | 微架构优化工具 | +| llvm-bolt | [https://gitee.com/src-openeuler/llvm-bolt](https://gitee.com/src-openeuler/llvm-bolt) | 二进制优化器 | + +## 使用流程 + +### 被优化应用的必要条件 + +1. 被优化二进制需要带有重定位信息。使用自编译的软件:需要在编译时增加`-Wl,-q`链接选项,如MySQL:`cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DBUILD_CONFIG=mysql_release -DWITH_BOOST=../boost -DCMAKE_C_LINK_FLAGS="-Wl,-q" -DCMAKE_CXX_LINK_FLAGS="-Wl,-q"`;使用oe软件包的场景:后续会提供对应应用的relocation包,直接安装即可。 +2. 如何判断目标二进制是否带有重定位信息:`-Wl,-q`生效后,二进制会增加RELA段,可以通过`readelf -SW /path/to/bin`来判断,如MySQL加选项之前,仅有`.rela.dyn`和`.rela.plt`段,增加后会出现`.rela.text`、`.rela.eh_frame`等10+ RELA段;如果`-Wl,-q`未生效,则在手动perf采样并执行`perf2bolt`时,或者执行`llvm-bolt`优化时(无论是否通过sysboost机制)会有告警:`BOLT-WARNING: non-relocation mode for AArch64 is not fully supported`。 + +### D-FOT准备 + +yum安装D-FOT或通过以下命令源码构建(注意如果libkperf或oeAware-manager也是源码构建,执行cmake时需要额外指定lib和include路径)。 + +```shell +cd D-FOT +mkdir build && cd build +cmake ../ -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_SKIP_RPATH=TRUE +make -j`nproc` + +cp build/libdfot.so /lib64/oeAware-plugin/ +chmod 440 /lib64/oeAware-plugin/libdfot.so +mkdir -p /etc/dfot/ +cp configs/dfot.ini /etc/dfot/ +``` + +### 配置修改 + +修改`/etc/dfot/dfot/ini`,内容项参考如下描述: + +公共配置:[general] + +| 配置项 | 值范围 | 是否可用 | 说明 | +| ----------------------------- | ----------------------------------- | ---- | -------------------------------------------------------------------------------------- | +| LOG_LEVEL | `` | 可用 | 优化服务日志级别,注意级别越低打印的日志越多 | +| COLLECTOR_SAMPLING_STRATEGY | `<0>` | 不可用 | 采样策略
0表示插件enable后即持续低频采样
1表示enable时启动监控线程,只有负载达到阈值场景才采样
当前由oeaware控制采样流程,仅支持0 | +| COLLECTOR_HIGH_LOAD_THRESHOLD | `[0, cpus*100]` | 不可用 | 仅在采样策略1场景下生效,使用HIGH_LOAD_THRESHOLD作为触发采样的应用CPU使用率阈值,当前不支持 | +| COLLECTOR_DATA_AGING_TIME | 按实际需要确定 | 可用 | 采样数据老化时间,当前数据与最老数据时间差值达到阈值时,丢弃累积采样数据,单位ms | +| TUNER_TOOL | `["sysboost"]` | 不可用 | 二进制优化器,当前仅支持sysboost | +| TUNER_CHECK_PERIOD | `[10, max]` | 可用 | 优化插件检查时间间隔,每隔一段时间收集采样插件数据并决定是否进行优化,单位ms | +| TUNER_PROFILE_DIR | 按实际需要确定 | 可用 | 采样数据存放位置,profile文件被命名为`[app_name]_[full_path_hash]_[threshold].profile` | +| TUNER_OPTIMIZING_STRATEGY | `[0, 1]` | 可用 | 优化策略,0表示只优化一次,1表示只要采样信息在刷新,可以持续多次优化 | +| TUNER_OPTIMIZING_CONDITION | `[0, 2]` | 不可用 | 触发优化的条件,0表示应用退出后即开始优化,1表示低负载时优化,2表示应用退出且低负载时优化,当前仅支持0 | + +应用配置:[app] + +| 配置项 | 值范围 | 是否可用 | 说明 | +| ----------------------------- | -------------- | ---- | ------------------------------------------------------------------------------------------ | +| FULL_PATH | 按实际需要确定 | 可用 | 应用二进制文件绝对路径 | +| DEFAULT_PROFILE | 按实际需要确定 | 可用 | 应用的开箱profile文件,用于冷启动时使能二进制优化,没有则留空 | +| COLLECTOR_DUMP_DATA_THRESHOLD | `[10000, max]` | 可用 | 采样数据达到该阈值行数时触发数据导出到profile,数值越大需要的采集的samples越多 | +| BOLT_DIR | NA | 不可用 | BOLT工具路径,留空则默认/usr/bin,内部会调用`${BOLT_DIR}/perf2bolt和${BOLT_DIR}/llvm-bolt`
当前由sysboost确定 | +| BOLT_OPTIONS | 按实际需要确定 | 可用 | BOLT优化选项,配置该项可以覆盖内置的默认选项,用于针对性的选项调优 | +| UPDATE_DEBUG_INFO | `[0, 1]` | 可用 | 优化时是否同步更新调试信息,1表示更新,0表示不更新,注意更新调试信息会有额外耗时 | + +### 插件使用 + +参考[oeAware-manager](https://gitee.com/openeuler/oeAware-manager/tree/master/docs)。 + +## 约束限制 + +1. 支持容器部署场景使用,D-FOT等优化组件需部署在容器外。 +2. 待优化的目标应用需要具备重定位信息。 +3. 作为oeAware调优插件使用D-FOT时,当前对应的oeAware采集插件pmu_sampling_collector固定采样频率为100,可能会导致采样时间较久(作为参考:perf默认采样频率为4000)。 + +## 未来规划 + +- [ ] 虚拟化场景完善 +- [ ] 运行时优化支持 +- [ ] 进一步提升二进制优化效果 diff --git a/docs/zh/gcc/gcc_14_secondary_version_compilation_toolchain_user_guide.md b/docs/zh/gcc/gcc_14_secondary_version_compilation_toolchain_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..42a4e9a7da5ad95a7c4b373386fe50f789dd1494 --- /dev/null +++ b/docs/zh/gcc/gcc_14_secondary_version_compilation_toolchain_user_guide.md @@ -0,0 +1,144 @@ +# GCC14副版本编译工具链 + +## 简介 + +为确保操作系统的稳健性,基础软件的选型策略通常倾向于采用经过时间验证、相对稳定的版本,而非最新发布版本。这一策略旨在避免版本更迭带来的潜在不稳定因素,确保在整个长期支持(LTS)周期内,系统版本保持相对稳定。因此,当前 openEuler 在 24.03 LTS 版本整个生命周期都是选择使用 GCC 12.3.1 作为基线进行开发。 + +这样的选择会带来如下问题。首先,许多的硬件特性需要基础 GCC 工具链的支持,选择非最新版本的 GCC 会导致新特性无法及时在新发布的操作系统上使能。另外,某些用户倾向使用最新版本的编译器使能最新特性,这些特性相较于低版本编译器会带来部分性能提升。 + +因此,为了使能多样算例新特性,满足不同用户对不同硬件特性支持的需求,在 openEuler 24.09 版本推出 openEuler GCC Toolset 工具链,这是一个专为 openEuler 系统设计的 GCC 多版本编译工具链,该工具链提供一个高于系统主 GCC 版本的副版本 GCC 编译工具链,为用户提供了更加灵活且高效的编译环境选择。通过使用 openEuler GCC Toolset 14 多版本编译工具链,用户可以轻松地在不同版本的 GCC 之间进行切换,以便充分利用新硬件特性,同时享受到 GCC 最新优化所带来的性能提升。 + +## 方案设计 + +### 编译工具链功能介绍 + +GCC 编译工具链是一套由 GNU 开发和维护的开源编译器集合,它是用于将高级语言代码转换为机器语言的工具集,GCC 编译工具链不仅包括GCC编译器本身,还包含一系列辅助工具和库,这些组件共同构成了一个完整的编译环境。 + +1. GCC 编译器(gcc/g++/gfrotran 等): + + * 作用:GCC 编译器是工具链的核心,负责完成预处理和编译过程,将源代码转换成汇编代码或中间表示。对于 C++ 代码,g++ 是 GCC 的 C++ 编译器前端,除了完成编译工作外,还会自动链接 C++ 标准库。 + +2. Binutils 工具集: + + * 包含工具:链接器(ld)、汇编器(as)、目标文件格式查看器(readelf)、符号查看器(nm)、目标文件格式转换工具(objcopy)、反汇编工具(objdump)、尺寸查看工具(size)等。 + * 作用:这些工具在编译过程中起辅助作用,如将汇编代码转换成机器码(汇编器)、将多个目标文件链接成可执行文件(链接器)、查看目标文件或可执行文件的信息(readelf、nm、objdump)等。 + +3. glibc 库: + + * 作用:glibc 是 GNU C Library 的缩写,是 GNU 组织为 GNU 系统以及 Linux 系统编写的 C 语言标准库。它包含了 C 语言中常用的标准函数,如 printf、malloc 等,是编译 C 语言程序时必不可少的部分。 + +4. 其他辅助工具: + + * 调试器(gdb):用于调试可执行文件,帮助开发者定位和解决程序中的错误。 + * 性能分析工具(gprof):用于分析程序的性能,帮助开发者优化代码。 + +### 工具链选型 + +在编译过程中,工具链中的软件组件对编译结果具有直接影响。具体而言,GCC、binutils 以及 glibc是其核心要素。glibc 作为 C 语言标准库,其选型通常与操作系统内核版本紧密绑定,不轻易进行更改。本工具链仅包含 GCC 和 binutils 两款软件来满足副版本编译需求。 + +当前最新的 GCC release 版本为 gcc-14.2.0,因此 openEuler GCC Toolset 工具链选型 的 GCC 的版本为gcc-14.2.0。 + +至于 binutils,openEuler 24.09 的默认 binutils 为 2.41 版本,而最新的 GCC-14 官方推荐搭配 binutils-2.42 使用,因此本工具链的 binutils 的版本选择 binutils-2.42。 + +基于此考量,openEuler GCC Toolset 副版本工具链引入 gcc-14.2.0 和 binutils-2.42,此举旨在确保编译环境的稳定性和效率,同时避免不必要的复杂性,力求在保障编译结果质量的同时,优化用户的使用体验。后期待 gcc-14.3.0 在上游社区 release 后,同步更新此工具链 GCC 版本。 + +### 架构设计 + +为区分于默认工具链安装,并防止 openEuler GCC Toolset 副版本编译工具链安装与默认编译工具链安装之间的依赖库冲突,将此工具链命名为 gcc-toolset-14,其软件包名均以前缀`gcc-toolset-14-`开头,后接原有工具链软件包名。同时,考虑到默认编译工具链安装路径为`/usr`,为避免路径重叠,特将 gcc-toolset-14 安装路径设定为`/opt/openEuler/gcc-toolset-14/`。为了与开源 GCC 做出区分,也便于后期合入更多 openEuler 社区特性,gcc-toolset-14-gcc 的版本设置为 14.2.1。 + +副版本编译工具链 gcc-toolset-14 提供的应用程序和库不会取代系统默认GCC版本,其包含的应用程序和库旨在与系统默认编译工具链版本并存,而非取代或覆盖它们,亦不会自动设为默认或首选选项。此外,为了实现低成本切换编译工具链版本,便于版本切换与管理,本方案引入 scl-utils 版本切换工具,具体使用和切换方式见下文。 + +## 安装与部署 + +### 软件要求 + +* 操作系统:openEuler 24.09 + +### 硬件要求 + +* Aarch64 / X86_64 + +### 安装方式 + +默认 GCC 编译器 gcc-12.3.1,安装路径为 /usr。 + +```shell +yum install -y gcc gcc-c++ +``` + +副版本编译工具链 gcc-toolset-14 安装路径为 /opt/openEuler/gcc-toolset-14/root/usr/。 + +```shell +yum install -y gcc-toolset-14-gcc* +yum install -y gcc-toolset-14-binutils* +``` + +## 使用方式 + +本方案引入 SCL(Software Collections)工具进行不同版本编译工具链的管理。 + +### SCL工具 + +SCL(Software Collections)是 Linux 系统中一个非常重要的工具,它为用户提供了一种方便、安全的安装和使用应用程序及运行时环境多个版本的方式,同时避免了系统混乱。 + +SCL 的主要用途包括: + +1. 多版本共存:允许用户在同一系统上安装和使用多个版本的软件库、工具和语言运行环境,从而满足不同应用和开发需求。 +2. 避免系统冲突:通过隔离不同版本的软件,避免了新版本软件与系统原有版本之间的冲突。 +3. 提升开发效率:对于开发人员来说,SCL 提供了最新的开发工具链和运行时环境,从而提升了开发效率。 + +### 版本切换方式 + +**安装 SCL:** + +```shell +yum install scl-utils scl-utils-build +``` + +**注册 gcc-toolset-14:** + +```shell +## 注册 gcc-toolset-14 +scl register /opt/openEuler/gcc-toolset-14/ + +## 取消注册 gcc-toolset-14 +scl deregister gcc-toolset-14 +``` + +使用 `scl list-collections` 显示 gcc-toolset-14 已经在 scl 中注册成功。 + +**切换 gcc-toolset-14:** + +```shell +scl enable gcc-toolset-14 bash +``` + +此命令会启动一个新的 bash shell 会话,使用 gcc-toolset-14 内的工具版本,而不是系统默认版本。在新的 bash shell 会话中,无需再显式切换编译器版本和路径。 +如果需要退出 gcc-toolset-14 的编译环境,输入 `exit` 退出 bash shell 会话,此时编译工具链的版本切换成系统默认版本。 + +SCL工具的本质就是自动设置不同工具版本的环境变量,具体可以参考 `/opt/openEuler/gcc-toolset-14/enable` 文档,gcc-toolset-14 的环境变量均在该文件中设置。若用户系统没有 SCL 工具,则可以使用以下方式进行工具链版本切换: + +```shell +## 方案一:无 SCL 工具,使用脚本切换编译工具链 +source /opt/openEuler/gcc-toolset-14/enable + +## 方案二:有 SCL 工具,使用 SCL 工具切换编译工具链并激活运行环境 +scl enable gcc-toolset-14 bash +``` + +## 使用约束 + +### 编译场景 + +主版本场景:正常编译使用系统默认的 gcc-12.3.1 进行构建。 + +副版本场景:需要使用 GCC-14 高版本特性构建相关应用,使用 SCL 工具将 bash 环境切换为 gcc-toolset-14 编译工具链的编译环境。 + +### 副版本GCC-14使用说明 + +1. openEuler GCC Toolset 14 副版本编译工具链提供如下两种使用方式: + + 1)动态链接:默认场景下会自动添加选项 -lstdc++ 进行动态链接,此时会链接系统库动态库 /usr/lib64/libstdc++.so.6 和 GCC-14 副版本提供的 libstdc++_nonshared.a 静态库,此静态库是 GCC-14 相比于 GCC-12 新增的稳定 C++ 特性;\ + 2)静态链接:用户使用选项 -static 进行静态链接,此时会链接 GCC-14 副版本提供的 libstdc++.a 全量特性静态库,该静态库路径为 `/opt/openEuler/gcc-toolset-14/root/usr/lib/gcc/aarch64-openEuler-linux/14/libstdc++.a`。 + +2. 用户默认构建使用动态链接,会链接新增的 libstdc++_nonshared.a 静态库,该库为了保持和系统兼容性,仅对 C++ 中正式标准特性进行封装。对于 -fmodules-ts,-fmodule-header 等选项,属于 C++20 的模块特性,而该特性在 C++20 中仍属于实验性质,并未封装在 libstdc++_nonshared.a 中,若用户需要使用此类新增特性,建议直接使用静态链接的方式全量链接 GCC-14 副版本的静态库。 diff --git a/docs/zh/gcc/gcc_optimization_user_guide.md b/docs/zh/gcc/gcc_optimization_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..e228c5e4303b7219f59024e95f28e5004bc887d1 --- /dev/null +++ b/docs/zh/gcc/gcc_optimization_user_guide.md @@ -0,0 +1,279 @@ +# GCC 优化特性用户指南 + +## 简介 + +编译器优化特性对于提高应用程序的开发效率、运行性能和可维护性都非常重要。它是计算机科学领域的一个重要研究方向,也是软件开发过程中的重要环节之一。GCC for openEuler 在通用编译优化能力的基础上,对中后端性能优化技术进行了增强,包括指令优化、向量化增强、预取增强、数据流分析增强等优化。 + +## 安装与部署 + +### 软件要求 + +操作系统:openEuler 24.03 LTS SP2 + +### 硬件要求 + +aarch64 架构 + +### 安装软件 + +按需安装 GCC 和相关组件即可,以 GCC 为例。 + +```shell +yum install gcc +``` + +## 使用方法 + +### CRC 优化 + +#### 说明 + +识别 CRC 软件循环代码,生成高效硬件指令。 + +#### 使用方法 + +在编译时增加 -floop-crc 选项。 + +注:`-floop-crc`选项需要和`-O3 -march=armv8.1-a`一起使用。 + +### If-conversion 增强 + +#### 说明 + +增强 If conversion 优化,使用更多的寄存器以减少冲突。 + +#### 使用方法 + +本优化是 RTL 优化 if-conversion 的一部分,使用如下编译选项控制优化启用。 + +`-fifcvt-allow-complicated-cmps` + +`--param=ifcvt-allow-register-renaming=[0,1,2]`数字用于控制优化范围。 + +注:此优化依赖`-O2`优化等级,以及与`--param=max-rtl-if-conversion-unpredictable-cost=48`、`--param=max-rtl-if-conversion-predictable-cost=48`共同使用。 + +### 乘法计算优化 + +#### 说明 + +Arm 相关指令合并优化,实现32位复杂组合的64位整形乘法逻辑的识别,并以高效的64位指令数输出。 + +#### 使用方法 + +使用`-fuaddsub-overflow-match-all`和`-fif-conversion-gimple`选项使能优化。 + +注:此优化需要`-O3`及以上优化等级。 + +### cmlt 指令生成优化 + +#### 说明 + +对一些四则运算生成`cmlt`指令,减少指令数。 + +#### 使用方法 + +使用选项`-mcmlt-arith`使能优化。 + +注:此优化需要`-O3`以上优化等级使用。 + +### 向量化优化增强 + +#### 说明 + +识别并简化向量化过程中生成的冗余指令,允许更短的循环进入向量化。 + +#### 使用方法 + +使用参数`--param=vect-alias-flexible-segment-len=1`使能,默认为0。 + +注:此优化需要`-O3`及以上优化等级。 + +### min max 和 uzp1/uzp2 指令联合优化 + +#### 说明 + +识别 min max 和 uzp1/uzp2 指令联合优化机会,减少指令数从而提升性能。 + +#### 使用方法 + +使用`-fconvert-minmax`选项使能`min max`优化,`uzp1/uzp2`指令优化在`-O3`以上等级默认使能。 + +注:依赖`-O3`及以上优化等级。 + +### ldp/stp 优化 + +#### 说明 + +识别某些性能表现差的 ldp/stp,将其拆分成2个 ldr 和 str。 + +#### 使用方法 + +使用`-fsplit-ldp-stp`选项使能优化,使用参数`--param=param-ldp-dependency-search-range=[1,32]`控制搜索范围,默认16。 + +注:依赖`-O1`及以上优化等级。 + +### AES指令优化 + +#### 说明 + +识别 AES 软件算法指令序列,使用硬件指令加速。 + +#### 使用方法 + +使用`-fcrypto-accel-aes`选项使能优化。 + +注:依赖`-O3`及以上优化等级。 + +### 间接调用提升 + +#### 说明 + +识别和分析程序中的间接调用,尝试将其优化为直接调用。 + +#### 使用方法 + +使用选项`-ficp -ficp-speculatively`使能优化。 + +注:此优化需要和`-O2 -flto -flto-partition=one`共同使用。 + +### IPA-prefetch + +#### 说明 + +识别循环中的间接访存,插入预取指令,从而减少间接访存的延迟。 + +#### 使用方法 + +通过选项`-fipa-prefetch -fipa-ic`使能优化。 + +注:此优化需要和`-O3 -flto`共同使用。 + +### -fipa-struct-reorg + +#### 说明 + +内存空间布局优化,将结构体成员在内存中的排布进行新的排列组合,来提高 cache 的命中率。 + +#### 使用方法 + +在选项中加入`-O3 -flto -flto-partition=one -fipa-struct-reorg`即可。 + +注:`-fipa-struct-reorg`选项,需要在`-O3 -flto -flto-partition=one`全局同时开启的基础上才使能。 + +### -fipa-reorder-fields + +#### 说明 + +内存空间布局优化,根据结构体中成员的占用空间大小,将成员从大到小排列,以减少边界对齐引入的 padding,来减少结构体整体占用的内存大小,以提高 cache 的命中率。 + +#### 使用方法 + +在选项中加入`-O3 -flto -flto-partition=one -fipa-reorder-fields`即可。 + +注:`-fipa-reorder-fields`选项,需要在`-O3 -flto -flto-partition=one`全局同时开启的基础上才使能。 + +### -ftree-slp-transpose-vectorize + +#### 说明 + +该选项在循环拆分阶段,增强对存在连续访存读的循环的数据流分析能力,通过插入临时数组拆分循环;SLP 矢量化阶段,新增对 grouped_stores 进行转置的 SLP 分析。 + +#### 使用方法 + +在选项中加入`-O3 -ftree-slp-transpose-vectorize`即可。 + +注:`-ftree-slp-transpose-vectorize`选项,需要在`-O3`开启的基础上才使能。 + +### LLC-prefetch + +#### 说明 + +通过分析程序中主要的执行路径,对主路径上的循环进行访存的复用分析,计算排序出 TOP 的热数据,并插入预取指令将数据先分配至 LLC 中,减少 LLC miss。 + +#### 使用方法 + +使能 LLC 特性,需开启 `-O2` 及以上优化等级,同时使用编译选项 `-fllc-allocate`。 + +其他相关接口: + +| 选项 | 默认值 | 说明 | +| ---- | ---- | ---- | +| --param=mem-access-ratio=[0,100] | 20 | 循环内访存数对指令数的占比。| +| --param=mem-access-num=unsigned | 3 | 循环内访存数量。 | +| --param=outer-loop-nums=[1,10] | 1 | 允许扩展的外层循环的最大层数。 | +| --param=filter-kernels=[0,1] | 1 | 是否针对循环做路径串联筛选。 | +| --param=branch-prob-threshold=[50,100] | 80 | 高概率执行分支的概率阈值。 | +| --param=prefetch-offset=[1,999999] | 1024 | 预取偏移距离,一般为2的次幂。 | +| --param=issue-topn=unsigned | 1 | 预取指令个数。 | +| --param=force-issue=[0,1] | 0 | 是否执行强制预取,即静态模式。 | +| --param=llc-capacity-per-core=[0,999999] | 107 | 多分支预取下每个核平均分配的 LLC 容量。 | + +### -fipa-struct-sfc + +#### 说明 + +静态压缩结构体成员,从而减小结构体整体占用的内存大小,以提高 cache 命中率。 + +#### 使用方法 + +在选项中加入`-O3 -flto -flto-partition=one -fipa-reorder-fields -fipa-struct-sfc`即可,可在此基础上使用`-fipa-struct-sfc-bitfield`、`-fipa-struct-sfc-shadow`开启额外优化。 + +注:`-fipa-struct-sfc`选项,需要在`-O3 -flto -flto-partition=one`全局同时开启以及开启`-fipa-reorder-fields`或`-fipa-struct-reorg>=2`的基础上才能使能。 + +### -fipa-struct-dfc + +#### 说明 + +动态压缩结构体成员,克隆程序路径并启发式压缩结构体大小,根据运行时检查选择运行路径,以提高 cache 命中率。 + +#### 使用方法 + +在选项中加入`-O3 -flto -flto-partition=one -fipa-reorder-fields -fipa-struct-dfc`即可,可在此基础上使用`-fipa-struct-dfc-bitfield`、`-fipa-struct-dfc-shadow`开启额外优化。 + +注:`-fipa-struct-dfc`选项,需要在`-O3 -flto -flto-partition=one`全局同时开启以及开启`-fipa-reorder-fields`或`-fipa-struct-reorg>=2`的基础上才能使能。 + +### -fipa-alignment-propagation + +#### 说明 + +分析并传播局部变量地址对齐值,优化按位与运算。 + +#### 使用方法 + +在选项中加入`-O3 -fipa-alignment-propagation`即可。 + +注:`-fipa-alignment-propagation`选项,需要在`-O3`开启的基础上才使能。 + +### -fipa-localize-array + +#### 说明 + +将由 calloc 分配的全局指针变量转换为局部变量。 + +#### 使用方法 + +在选项中加入`-O3 -fipa-localize-array`即可。 + +注:`-fipa-localize-array`选项,需要在`-O3`开启的基础上才使能。 + +### -fipa-array-dse + +#### 说明 + +分析数组在函数之间的传递情况以及在被调用函数中的使用情况,消除冗余的数组写入。 + +#### 使用方法 + +在选项中加入`-O3 -fipa-array-dse`即可。 + +注:`-fipa-array-dse`选项,需要在`-O3`开启的基础上才使能。 + +### -ffind-with-sve + +#### 说明 + +识别 `std::find` 函数调用,尝试使用 SVE 指令优化。 + +#### 使用方法 + +在选项中加入 `-ffind-with-sve` 即可。 diff --git a/docs/zh/gcc/kernel_fdo_user_guide.md b/docs/zh/gcc/kernel_fdo_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..140dba1c10df517c6e8aaa32e58dfb9577cddb77 --- /dev/null +++ b/docs/zh/gcc/kernel_fdo_user_guide.md @@ -0,0 +1,68 @@ +# 内核反馈优化特性用户指南 + +## 简介 + +内核反馈优化(PGO kernel)特性为内核提供了反馈优化能力的支持,使用户可以为不同的应用程序构建针对性优化的内核,在单应用场景下提高目标应用的性能。同时,该特性一并在openEuler GCC内提供了相应的编译支持,以及在A-FOT中提供了自动优化的功能,使用户能够便捷地使能内核反馈优化特性。 + +## 安装与部署 + +### 软件要求 + +* 操作系统:openEuler 23.09 + +### 硬件要求 + +* aarch64架构 +* x86_64架构 + +### 安装软件 + +安装内核源码、A-FOT和其他依赖软件包: + +```shell +yum install -y kernel-source A-FOT make gcc flex bison elfutils-libelf-devel diffutils openssl-devel dwarves +``` + +复制内核源码: + +```shell +cp -r /usr/src/linux-6.4.0-8.0.0.16.oe2309.aarch64 . +``` + +**注意:具体的版本号可能会有变化。** + +## 使用方法 + +用户可以通过A-FOT工具使能内核反馈优化,一键得到优化内核。将opt_mode指定Auto_kernel_PGO则为PGO kernel模式。所有配置选项也可以通过命令行指定,例如./a-fot --pgo_phase 1,另外-s、-n选项只能在命令行指定。PGO kernel相关的选项说明如下表所示。 + +| 序号 | 选项名称(配置文件) | 选项说明 | 默认值 | +| ---- | -------------------- | ------------------------------------------------------------ | ------------------------ | +| 1 | config_file | 配置文件路径;根据此文件内容读取用户的选项配置。 | ${afot_path}/a-fot.ini | +| 2 | opt_mode | 优化模式;工具将执行的优化模式,必须为AutoFDO、AutoPrefetch、AutoBOLT、Auto_kernel_PGO四者之一;分别代表自动反馈优化、自动预取、自动二进制优化和自动内核反馈优化。 | AutoPrefetch | +| 3 | pgo_mode | PGO模式;内核的反馈优化模式,GCOV或完整的PGO*,必须为arc或all;分别代表仅使用arc profile和使用arc+value profile。 | all | +| 4 | pgo_phase | 内核反馈优化的执行阶段;工具根据阶段执行不同的操作,必须为1或2;1代表编译插桩内核的阶段,2代表收集数据、编译优化内核的阶段。 | 1 | +| 5 | kernel_src | 内核源码目录;指定则工具进入编译内核,否则工具自动下载源码。 | 无(可选) | +| 6 | kernel_name | 内核构建的本地名;工具将根据阶段添加`-pgoing`或`-pgoed`后缀。 | kernel | +| 7 | work_path | 脚本工作目录;此目录用于存放日志文件、wrapper和profile。 | /opt(不能在/tmp目录下) | +| 8 | run_script | 应用执行脚本路径;此脚本为目标应用的执行脚本,需要用户完成编写;工具将后台运行此脚本以执行目标应用。 | /root/run.sh | +| 9 | gcc_path | GCC路径;工具调用真正编译器GCC的路径。 | /usr | +| 10 | -s | 安静模式;工具自动重启系统切换内核、执行第二阶段。 | 无 | +| 11 | -n | 不要让工具来编译内核;适用于执行环境和内核编译环境分离的场景。 | 无 | + +配置完编译选项后,可以使用如下命令进行A-FOT自动化优化内核: + +```shell +a-fot --config_file ./a-fot.ini -s +``` + +**注意:-s选项会让A-FOT工具自动重启机器切换内核,如果用户不希望自动进行这一项敏感操作,请去掉这一选项。但用户需要在重启后手动执行第二阶段(--pgo_phase 2)。** + +**注意:所有路径名请使用绝对路径。** + +**注意:openEuler 23.09版本的内核暂不支持完整的PGO,请修改pgo_mode值为arc。** + +## 兼容性说明 + +此节主要列出当前一些特殊场景下的兼容性问题。本项目持续迭代中,会尽快进行修复,也欢迎广大开发者加入。 + +* openEuler 23.09版本的内核暂不支持完整的PGO,目前只支持arc模式。 diff --git a/docs/zh/gcc/lto_user_guide.md b/docs/zh/gcc/lto_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..69b26b2f9de61a7ea29d04c02ebfa143f8cd1a8f --- /dev/null +++ b/docs/zh/gcc/lto_user_guide.md @@ -0,0 +1,27 @@ +# 链接时优化特性 + +## 链接时优化简介 + +在传统编译流程中,gcc 将单个源文件(称谓一个编译单元)直接进行编译优化生成包含汇编代码的`.o`目标对象文件,并由链接器对这些`.o`文件进行符号表解析与重定位,链接成可执行文件。在这个过程中,拥有跨文件函数调用信息的链接器由于操作的是汇编代码,难以进行编译优化,而可以执行编译优化的环节,却没有跨文件的全局信息。这样的编译框架,虽然提高了编译效率,每次重新编译只需要编译修改过的少量编译单元,但也丢失了许多跨文件的优化机会。 + +链接时优化(LTO),设计的初衷就是希望能够在链接时,拥有跨编译单元的调用信息的时候,进行编译优化,提供更多的优化机会。为了达到这个目的,LTO 需要将编译优化所需的 IR 信息保留到链接时。在链接时,链接器会调用 LTO 插件,执行全程序分析,生成更加有效的优化决策,再经由编译优化生成更高效的IR,进一步转成包含汇编代码的目标对象文件,最后由链接器完成常规的链接工作。 + +## 版本构建使能 + +### 背景 + +为了获得更优的性能与更小的二进制体积,许多海外社区已经在版本构建中使用了链接时优化,链接时优化也正在成为各方寻找编译优化机会的新战场。openEuler 计划从 24.09 创新版本开始,在版本构建中引入 LTO。 + +### 方案 + +我们将在 openEuler-rpm-config 的 macro 中所包含的全局编译选项中插入 `-flto -ffat-lto-objects`,以达到在构建软件包是使能 lto 的效果。其中 `-flto` 用以使能链接时优化,而 `-ffat-lto-objects` 用以生成同时包含 LTO 对象信息和常规链接所需的汇编信息的胖目标对象。在当前构建中,LTO 对象信息会参与 LTO 优化,而由于 LTO 目标对象文件在不同版本的 gcc 之间是不通用的,因此在打包生成对应的 `.rpm` 包之前,我们会将 `.o/.a` 文件中的 LTO 相关字段给消除,仅保留常规链接所需的汇编代码信息,不对静态库本身产生影响。 + +### 使能范围 + +由于 LTO 的编译流程与常规的编译流程相差较大,影响较广,为了控制 LTO 对版本质量的冲击,我们当前仅对 500+ 个软件包使能了 lto,你可以在 `/usr/lib/rpm/%{_vendor}/lto_white_list` 中找到这些软件包的清单。这些白名单应用在使能了 LTO 之后构建成功,并通过了自带的测试套。lto 编译选项仅在构建白名单应用时被设置为 `-flto -ffat-lto-objects`,否则置为空。 + +我们会在后续的创新版本上,联合应用维护者,扩大 LTO 使能的范围。 + +### 注意事项 + +当前热补丁机制与 LTO 仍存在不兼容,热补丁在 LTO 开启时会失效。我们已与热补丁团队就解决方式达成一致,会在后续版本中解决该问题。 diff --git a/docs/zh/gcc/pin_user_guide.md b/docs/zh/gcc/pin_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..cf2f7acbb79abc6853d2e6155f998e845269adb0 --- /dev/null +++ b/docs/zh/gcc/pin_user_guide.md @@ -0,0 +1,134 @@ +# 安装与部署 + +## 软件要求 + +* 操作系统:openEuler 23.03 + +## 硬件要求 + +* x86_64架构 +* ARM架构 + +## 环境准备 + +* 安装openEuler系统,安装方法参考[《安装指南》](https://docs.openeuler.openatom.cn/zh/docs/24.03_LTS_SP2/server/installation_upgrade/installation/installation_on_servers.html)。 + +### 安装依赖软件 + +#### 安装插件框架GCC客户端依赖软件 + +```shell +yum install -y grpc +yum install -y grpc-devel +yum install -y grpc-plugins +yum install -y protobuf-devel +yum install -y jsoncpp +yum install -y jsoncpp-devel +yum install -y gcc-plugin-devel +yum install -y llvm-mlir +yum install -y llvm-mlir-devel +yum install -y llvm-devel +``` + +#### 安装插件框架服务端依赖软件 + +```shell +yum install -y grpc +yum install -y grpc-devel +yum install -y grpc-plugins +yum install -y protobuf-devel +yum install -y jsoncpp +yum install -y jsoncpp-devel +yum install -y llvm-mlir +yum install -y llvm-mlir-devel +yum install -y llvm-devel +``` + +## 安装Pin + +### rpm构建 + +#### 构建插件框架GCC客户端 + +```shell +git clone https://gitee.com/src-openeuler/pin-gcc-client.git +cd pin-gcc-client +mkdir -p ~/rpmbuild/SOURCES +cp *.path pin-gcc-client.tar.gz ~/rpmbuild/SOURCES +rpmbuild -ba pin-gcc-client.spec +cd ~/rpmbuild/RPMS +rpm -ivh pin-gcc-client.rpm +``` + +#### 构建插件框架服务端 + +```shell +git clone https://gitee.com/src-openeuler/pin-server.git +cd pin-server +mkdir -p ~/rpmbuild/SOURCES +cp *.path pin-server.tar.gz ~/rpmbuild/SOURCES +rpmbuild -ba pin-server.spec +cd ~/rpmbuild/RPMS +rpm -ivh pin-server.rpm +``` + +### 编译构建 + +#### 构建插件框架GCC客户端 + +```shell +git clone https://gitee.com/openeuler/pin-gcc-client.git +cd pin-gcc-client +mkdir build +cd build +cmake ../ -DMLIR_DIR=${MLIR_PATH} -DLLVM_DIR=${LLVM_PATH} +make +``` + +#### 构建插件框架服务端 + +```shell +git clone https://gitee.com/openeuler/pin-server.git +cd pin-server +mkdir build +cd build +cmake ../ -DMLIR_DIR=${MLIR_PATH} -DLLVM_DIR=${LLVM_PATH} +make +``` + +# 使用方法 + +用户可以通过`-fplugin`和`-fplugin-arg-libpin_xxx`使能插件工具。 +命令如下: + +```shell +$(TARGET): $(OBJS) + $(CXX) -fplugin=${CLIENT_PATH}/build/libpin_gcc_client.so \ + -fplugin-arg-libpin_gcc_client-server_path=${SERVER_PATH}/build/pin_server \ + -fplugin-arg-libpin_gcc_client-log_level="1" \ + -fplugin-arg-libpin_gcc_client-arg1="xxx" +``` + +为了方便用户使用,可以通过`${INSTALL_PATH}/bin/pin-gcc-client.json`文件,进行插件配置。配置选项如下: + +`path`:配置插件框架服务端可执行文件路径。 + +`sha256file`:配置插件工具的校验文件`xxx.sha256`路径。 + +`timeout`:配置跨进程通信超时时间,单位`ms`。 + +编译选项: + +`-fplugin`:指定插件客户端`.so`所在路径。 + +`-fplugin-arg-libpin_gcc_client-server_path`:指定插件服务端可执行程序所在路径。 + +`-fplugin-arg-libpin_gcc_client-log_level`:指定日志系统默认记录等级,取值`0~3`。默认为`1`。 + +`-fplugin-arg-libpin_gcc_client-argN`:用户可以根据插件工具要求,指定其他参数。argN代指插件工具要求的参数字段。 + +# 兼容性说明 + +此节主要列出当前一些特殊场景下的兼容性问题。本项目持续迭代中,会尽快进行修复,也欢迎广大开发者加入。 + +* 插件框架在`-flto`阶段使能时,不支持使用`make -j`多进程编译。建议改用`make -j1`进行编译。 diff --git a/docs/zh/llvm/_toc.yaml b/docs/zh/llvm/_toc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1d60de7bbb1042e99f60e47a6360e197588d79f3 --- /dev/null +++ b/docs/zh/llvm/_toc.yaml @@ -0,0 +1,12 @@ +label: LLVM用户指南 +isManual: true +description: LLVM for openEuler 编译器基于开源 LLVM 开发 +sections: + - label: LLVM反馈优化特性 + href: ./llvm_pgo_user_guide.md + - label: 内核反馈优化特性 + href: ./kernel_pgo_user_guide.md + - label: GNU兼容性 + href: ./gnu_compatibility_user_guide.md + - label: 新增架构支持 + href: ./more_architecture_supported.md \ No newline at end of file diff --git a/docs/zh/llvm/figures/figure_pgo_0.png b/docs/zh/llvm/figures/figure_pgo_0.png new file mode 100644 index 0000000000000000000000000000000000000000..8a4bc807f1579202d2df5fbcca592edea6cb70b2 Binary files /dev/null and b/docs/zh/llvm/figures/figure_pgo_0.png differ diff --git a/docs/zh/llvm/figures/figure_pgo_1.png b/docs/zh/llvm/figures/figure_pgo_1.png new file mode 100644 index 0000000000000000000000000000000000000000..db068a1491b6ae2b313f19213da50219e3ab3bc8 Binary files /dev/null and b/docs/zh/llvm/figures/figure_pgo_1.png differ diff --git a/docs/zh/llvm/figures/figure_pgo_2.png b/docs/zh/llvm/figures/figure_pgo_2.png new file mode 100644 index 0000000000000000000000000000000000000000..e7096da9e3f6e6ebe4c159ace8078b568785a605 Binary files /dev/null and b/docs/zh/llvm/figures/figure_pgo_2.png differ diff --git a/docs/zh/llvm/figures/figure_pgo_3.png b/docs/zh/llvm/figures/figure_pgo_3.png new file mode 100644 index 0000000000000000000000000000000000000000..c38cae90f81b4f4ecfb1072dcb30f9df72b42c51 Binary files /dev/null and b/docs/zh/llvm/figures/figure_pgo_3.png differ diff --git a/docs/zh/llvm/figures/figure_pgo_4.png b/docs/zh/llvm/figures/figure_pgo_4.png new file mode 100644 index 0000000000000000000000000000000000000000..7f437a1a8f33ebbc1fc79e4d43c700204b536e97 Binary files /dev/null and b/docs/zh/llvm/figures/figure_pgo_4.png differ diff --git a/docs/zh/llvm/figures/figure_pgo_5.png b/docs/zh/llvm/figures/figure_pgo_5.png new file mode 100644 index 0000000000000000000000000000000000000000..9068cb0d90b369710d3e1b24a92dd838563310d3 Binary files /dev/null and b/docs/zh/llvm/figures/figure_pgo_5.png differ diff --git a/docs/zh/llvm/gnu_compatibility_user_guide.md b/docs/zh/llvm/gnu_compatibility_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..8991ee1df26ba7e91c9bd275a705fa3850b35eb5 --- /dev/null +++ b/docs/zh/llvm/gnu_compatibility_user_guide.md @@ -0,0 +1,675 @@ +# GNU 兼容性 + +## 简介 + +相比 GNU 编译器,LLVM 前端 Clang 对语法的检查更严谨,严格匹配语言标准,Clang 的常见兼容性和可移植性问题,请参考[开源官方文档](https://clang.llvm.org/compatibility.html)。本文主要列出一些 LLVM for openEuler 相对 GNU 编译器不支持的问题以及部分固有实现,以供用户参考。LLVM for openEuler 针对 GNU 编译器进行了一定程度的兼容,并提供针对 GNU 编译器的整体兼容选项 `-fGNU-compatibility`。 + +## -Werror 引入的问题 + +### 错误信息 + +在编译选项打开 `-Werror` 的情况下,编译器会将所有 warning 转化为 error,不同于 warning,error 会阻碍构建。此类 error 格式如下: + +```shell +test.c:6:1: error: non-void function does not return a value [-Werror,-Wreturn-type] +``` + +### 问题介绍 + +因为 LLVM 编译器和 GNU 编译器对于 warning 的处理有差异,因此可能存在切换 LLVM 后,新增 warning 并被 `-Werror` 选项转化为 error,阻碍构建的情况。 + +### 解决方案 + +可以通过增加 `-Wno` 选项关闭对应的 warning,例如上例中 warning 提示告警来自 `-Wreturn-type` 选项,则可添加 `-Wno-return-type`(`W` 后添加 `no-`)选项关闭该告警,可以通过在源码根目录 `grep -Werror` 找到设置 `-Werror` 选项的位置,并在该处添加对应的 `-Wno` 选项。openEuler 中的 LLVM17 版本可通过打开 `-fGNU-compatibility` 选项,控制大部分与 GNU 编译器存在差异的 warning 不被 `-Werror` 选项升级,批量解决该问题。 + +## 选项兼容问题 + +### 问题介绍 + +因为 LLVM 编译器和 GNU 编译器支持的选项功能存在差异,因此可能存在切换 LLVM 后,部分编译选项不识别导致报错。 + +包括但不限于: + +```shell +-znow +# error: unknown argument: `-znow` + +-mabi=lp64 +# error: unknown target ABI 'lp64' + +clang -std=c++11 +# error: invalid argument '-std=c++11' not allowed with 'C' + +-Wa,--generate-missing-build-notes=yes +# clang: error: unsupported argument '--generate-missing-build-notes=yes' to option '-Wa,' +``` + +### 解决方式 + +1. 去除相关选项或使用 LLVM 支持的相关选项替代。 + +2. openEuler 中的 LLVM17 版本包含一系列选项兼容适配特性,使用部分选项编译时会自动适配 GNU 行为,避免生成阻塞性告警。 + +## Clang 不支持问题 + +### 不支持 print-multi-os-directory + +#### 错误信息 + +```shell +ERROR: Problem encountered: Cannot find elf_aarch64_efi.lds +``` + +#### 问题介绍 + +GCC 使用 `print-multi-os-directory`,该选项返回 `../lib64`,而 Clang 不支持该选项,故无法组成完整的路径,因此找不到某些文件。 + +#### 解决方案 + +在编译时,对需要通过选项获取 lib 路径的代码进行硬编码。 + +### 不支持 __builtin_longjmp/__builtin_setjmp + +#### 错误信息 + +```shell +error: __builtin_longjmp is not supported for the current target + __builtin_longjmp (buf, 1); + ^~~~~~~~~~~~~~~~~~~~~~~~~~ +error: __builtin_setjmp is not supported for the current target + int r = __builtin_setjmp (buf); + ^~~~~~~~~~~~~~~~~~~~~~ +``` + +#### 问题介绍 + +当前 AArch64 后端不支持内置函数 `__builtin_longjmp` 和 `__builtin_setjmp`。 + +#### 解决方案 + +- 使用标准库中的setjmp/longjmp。 + +- 编译器后续支持。 + +### 32 位下不支持 __uint128_t + +#### 错误信息 + +```shell +clang: warning: unknown platform, assuming -mfloat-abi=soft +error: unknown type name '__uint128_t' +``` + +#### 问题介绍 + +在 32 位模式下编译(例如添加了 `-m32` 参数)报错:`__uint128` 不被支持。 + +除此之外,还可能看到一个平台无法识别的 warning:使用 `-mfloat-abi=soft` 参数将浮点运算编译为软浮点。 + +#### 解决方案 + +- 去除 `-m32` 参数,使用 64 位模式编译。 + +- 检查 Makefile、configure 等构建脚本的平台判断流程,使用正确的平台选项编译。 + +### 不支持选项 -aux-info + +#### 错误信息 + +无报错信息。 + +#### 问题介绍 + +`-aux-info` 选项用于将编译单元中声明或定义的所有函数(包括头文件中的函数)输出到给定的输入文件。 + +该选项一般用于从 `*.c` 自动生成 `*.h` 文件。 + +Clang 不支持这个选项。 + +#### 解决方案 + +避免使用 Clang 不支持的选项。 + +如果确实需要这些信息,可以通过预处理器处理之后,用 `sed/aux` 等命令提取出想要的函数信息。 + +例如: + +```shell +clang -E -xc test.c | sed -n 's/^extern * int *\(\w*\) *(.*$/\1/p' +``` + +### 不支持 __builtin___snprintf_chk + +#### 错误信息 + +```shell +error: no member named '__builtin___snprintf_chk' in +``` + +#### 问题介绍 + +Clang 暂不支持检查 built-in 函数格式化输出,会报出 warning,当开启 `-Werror` 选项时升级为 error。 + +#### 解决方案 + +添加编译选项-Wno-builtin-memcpy-chk-size规避该告警。 + +### 不支持 NEON 指令 + +#### 错误信息 + +```shell +error: unknown register name 'q0' in asm + : "memory", "cc", "q0" + ^ +``` + +#### 问题介绍 + +Clang 中不支持 NEON 指令 Q 寄存器设计。 + +代码示例: + +```shell +$ cat bar.c +int foo(void) { + __asm__("":::"q0"); + return 0; +} +$ clang bar.c +bar.c:2:16: error: unknown register name 'q0' in asm + __asm__("":::"q0"); + ^ +1 error generated. +``` + +#### 解决方案 + +修改 `qX` 寄存器为 `vX` 寄存器。 + +### 不支持部分运行库 + +#### 错误信息 + +```shell +undefined reference to `__muloti4' +``` + +#### 问题介绍 + +某符号不在 libgcc 中,但是在 compiler-rt 中,特别是使用 Clang 的 `__builtin_*_overflow` 家族的内联函数时。 + +#### 解决方案 + +使用 `--rtlib=compiler-rt` 来启用 compiler-rt,注意目前并不支持所有平台。 + +如果使用 libc++ 或者 libc++abi,使用 compiler-rt 而不是 libgcc_s,通过在 cmake 中添加 `-DLIBCXX_USE_COMPILER_RT=YES` 和 `-DLIBCXXABI_USE_COMPILER_RT=YES` 实现。否则可能会链接两个运行时库,虽然不影响功能但是造成性能浪费。 + +参考 [LLVM 官方说明](https://clang.llvm.org/docs/Toolchain.html)。 + +### 不支持原子类型(atomic type)的类型转换 + +#### 错误信息 + +```shell +error: used type '_Atomic(int_fast32_t)' where arithmetic or pointer type is required + uint32_t(_Atomic(int_fast32_t))(1) + ^ +``` + +#### 问题介绍 + +Clang 拒绝对非标准类型的类型转换,并且目前不支持对原子类型(atomic type)的转换。所支持的类型在 `clang/include/clang/AST/BuiltinTypes.def` 中有列出,不包括原子类型。 + +#### 解决方案 + +避免对原子类型使用类型转换。 + +## 链接问题 + +### 指定 pic、pie + +#### 错误信息 + +某些动态库在未使用 pic/pie 选项的情况下,会报符号表缺失的错误,比如: + +```shell +undefined reference to `cmsPlugin' +``` + +#### 问题介绍 + +生成动态库与 pie 可执行文件编译或链接时未带对应 pic/pie 选项,导致符号表缺失,需要手动指定。 + +#### 代码示例 + +执行如下命令检查是否为 PIC 库,检索到 textrel 符号则表明是 PIC 库。 + +```shell +readelf -a libhello.so |grep -i textrel +``` + +检查是否为 PIE 共享文件,使用 `file` 命令查看,或者用 `size --format=sysv` 查看基地址是否在 0 附近。 + +#### 解决方案 + +编译选项增加 `-fPIC`,链接选项增加 `-pie`。 + +> [!WARNING]注意 +> Clang 严格区分编译和链接选项,不能通过 cflags 将 `-pie` 传递给链接器,否则会报错: +> `clang: error: argument unused during compilation: '-pie' [-Werror,-Wunused-command-line-argument]`。 + +### 给链接器参数加上 -Wl + +#### 错误信息 + +```shell +clang: error: unsupported option `--whole-archive` +clang: error: unsupported option `--no-whole-archive` +clang: error: unknown argument: `-soname` +``` + +#### 问题介绍 + +部分应用构建脚本在编译器为 clang 时可能不会默认给需要传递给链接器加上 `-Wl`,这部分参数必须添加 `-Wl`,才能传递给链接器。 + +包括但不限于: + +```shell +--whole-archive +--no-whole-archive +-soname +``` + +如果出现 `unknown argument` 或者 `unsupported option`,并且该选项是应该传给链接器的,则需要加上 `-Wl`。 + +#### 解决方案 + +这些参数前面添加 `-Wl,`。例如: + +```shell +-Wl,--whole-archive -Wl,--no-whole-archive -Wl,-soname +``` + +### Clang 不再默认传递 --build-id 到链接器 + +#### 错误信息 + +```shell +ERROR: No build ID note found in xxx.so +``` + +#### 问题介绍 + +为了避免额外链接器开销,Clang 不再默认传递 `--build-id` 到链接器。 + +#### 解决方案 + +编译目标源码时增加 `-Wl,--build-id` 选项可以临时传递。 + +### 系统 libstdc++ 库版本过低导致符号未定义或运行结果错误 + +#### 错误信息 + +无法找到高版本 C++ 标准库函数定义的接口: + +```shell +undefined reference to `std::xxx` +``` + +#### 问题介绍 + +Clang 默认使用系统路径下的 `libstdc++.so` 动态库,过低的系统 `libstdc++.so` 库版本可能不支持用户代码中使用的高版本特性,导致链接时出现未定义符号或运行结果错误。 + +#### 解决方案 + +链接时加入 `-stdlib=libc++` 或 `-lc++` 选项,使用 Clang 提供的 `libc++.so` 库中提供的标准 C++ 库实现。 + +### 系统 binutils 版本过低导致 debug_info 段链接失败 + +#### 错误信息 + +```shell +unable to initializedecompress status for section .debug_info +``` + +#### 问题介绍 + +在 x86_64 环境 CentOS 7.6、Ubuntu 18.04 系统上运行时,如果系统默认的 binutils 版本低于 2.32,会由于低版本 binutils 对调试信息段的对齐处理有误,导致在链接时如果链接由高版本(版本 >2.32)binutils 生成的 debug_info 段链接失败。 + +#### 解决方案 + +1. 在链接时使用 `-fuse-ld=lld` 选项,选择 LLVM for openEuler 自带的链接器即可。 + +2. 如仍然需要 GNU 链接器,请升级系统链接器到 2.32 版本以上。 + +## 其他类兼容问题 + +### Clang 预处理器结果与 GCC 存在较大差异 + +#### 错误信息 + +- 格式错误:syntax error, unexpected IDENT + +- 找不到头文件等。 + +#### 问题介绍 + +Clang 的预处理器实现和 GCC 有比较大的不同,例如: + +- Clang 会保留每行开头的空白符。 + +- Clang 会保留引入的头文件的绝对路径。 + +其它的不一一列举。 + +有一些程序会使用预处理器来处理源码文件,但是因为Clang和GCC的预处理器的行为有一些不同,可能会因此导致一些问题。 + +#### 解决方案 + +修改源码使得其能被 Clang 的预处理器正确处理。例如: + +- 删除代码行前的空白符。 + +- 保证include的文件能被找到。 + +### Clang不支持在使用`-o`指定输出时直接添加头文件 + +#### 错误信息 + +```shell +clang test.h test.c -o test +clang: error: cannot specify -o when generating multiple output files +``` + +#### 问题介绍 + +Clang 不支持在使用 `-o` 指定输出文件时直接添加头文件,但允许在编译命令中使用预编译头文件,以减少编译时间。 + +```shell +$ cat test.c +#include "test.h" +``` + +生成预编译头文件的命令: + +```shell +clang -x c-header test.h -o test.h.pch +``` + +可以通过添加 `-include` 命令使用预编译头文件: + +```shell +clang -include test.h test.c -o test +``` + +Clang 会先检查 `test.h` 对应的预编译头文件是否存在;如果存在,则会使用对应的预编译头文件对 `test.h` 进行处理,否则,Clang 会直接处理 `test.h` 的内容。 + +如果设法在 Clang 编译命令中保留头文件,则可以通过添加命令 `-include` 的方法使其通过编译。 + +[官方参考文档](https://clang.llvm.org/docs/UsersManual.html) + +#### 解决方案 + +避免在 Clang 的编译命令中直接添加头文件,或者按照上述方法使用预编译功能。 + +### 不同编译器对 built-in includes 的实现不同 + +#### 错误信息 + +```shell +error: typedef redefinition with different types ('__uint64_t' (aka 'unsigned long') vs 'UINT64' (aka 'unsigned long long')) +error: unknown type name 'wchar_t' +``` + +#### 问题介绍 + +某些头文件(例如 `stdatomic.h`、`stdint.h`)是由编译器实现的,不同的编译器对于这些文件的实现存在差异,因此使用 GCC 头文件实现的程序,切换到 Clang 之后,用户自定义的代码可能会与 Clang 头文件发生冲突。 + +比如说重定义问题:在 Clang 的某些头文件中定义了一些在对应 GCC 的头文件中没有定义的变量,而用户在自己编写的或引入的其它库的头文件也定义了该变量,变量被重复定义,导致 redefinition 错误。 + +又或者:在 GCC 的 built-in 头文件中定义了一些变量,而 Clang 对应的头文件中没有定义该变量,用户在自己编写的代码中直接使用了该变量,结果就会导致 unknown type 的错误。 + +#### 解决方案 + +建议修改源码。 + +### 不同编译器链接的OpenMP运行时库不同 + +#### 错误信息 + +- 测试错误 + +- 无法加载OpenMP运行时库 + +#### 问题介绍 + +Clang 编译的可执行程序链接的 OpenMP 运行时库叫 `libomp.so`,GCC 链接的叫 `libgomp.so`。 + +#### 解决方案 + +确保能够找到 `libomp.so`。 + +- 将 `libomp.so` 所在的目录(例如 `{$INSTALLATION_HOME}/lib,INSTALLATION_HOME` 为安装根目录)添加到环境变量 `LD_LIBRARY_PATH`。 + +- 或者安装libomp: + + ```shell + yum install libomp -y + ``` + +### __builtin_prefetch 语义检查错误 + +#### 错误信息 + +```shell + error: argument to '__builtin_prefetch' must be a constant integer + __builtin_prefetch(address, forWrite); + ^ +``` + +#### 问题介绍 + +在这段代码中,因为 `__builtin_prefetch` 的第二个参数需要是常量,所以先用 `__builtin_constant_p` 检查 `forWrite` 是否是常量。但是,对于 Clang 而言,会出现语义检查错误。 + +#### 代码示例 + +```c +static void prefetchAddress(const void *address, bool forWrite) { + if (__builtin_constant_p(forWrite)) { + __builtin_prefetch(address, forWrite); + } +} +``` + +#### 解决方案 + +将函数转换为宏函数: + +```c +##define prefetchAddress(address,forWrite) do{\ + if (__builtin_constant_p(forWrite)) { \ + __builtin_prefetch(address, forWrite); \ + } \ +}while(0) +``` + +### 找不到符号 perl_tsa_mutex_lock + +#### 错误信息 + +```shell +Can't load 'xxx.so' for module threads: xxx.so: undefined symbol: perl_tsa_mutex_lock at xxx +``` + +#### 问题介绍 + +在文件 `/usr/lib64/perl5/CORE/perl.h` 中有如下的定义: + +```c +##if ... + defined(__clang__) + ... +## define PERL_TSA__(x) __attribute__((x)) +## define PERL_TSA_ACTIVE +##else +## define PERL_TSA__(x) /* No TSA, make TSA attributes no-ops. */ +## undef PERL_TSA_ACTIVE +##endif + +##ifdef PERL_TSA_ACTIVE +EXTERN_C int perl_tsa_mutex_lock(perl_mutex* mutex) + PERL_TSA_ACQUIRE(*mutex) + PERL_TSA_NO_TSA; +EXTERN_C int perl_tsa_mutex_unlock(perl_mutex* mutex) + PERL_TSA_RELEASE(*mutex) + PERL_TSA_NO_TSA; +##endif##endif +``` + +由于针对 Clang 使用的 mutex 相关的符号是有线程安全标记的 `perl_tsa_*`,但是 `libperl.so` 并不包含这些符号,故而出现链接错误。 + +#### 解决方案 + +- 使用包含 `perl_tsa_*` 符号的 `libperl.so`(在编译 `libperl.so` 时,加上宏 `USE_ITHREADS` 和 `I_PTHREAD`)。 + +- 去除预定义宏 `__clang__`: + + ```c + clang -U__clang__ ... + ``` + +### Clang 宏问题 + +#### 问题介绍 + +程序代码逻辑使用了 `__GNUC__` 的宏作为判断依据,但是 GCC 与 Clang 中定义的宏内容不一致,可以使用如下命令确认 Clang 中宏定义的值。 + +```shell +clang -x c /dev/null -dM -E >clang.log;cat clang.log|grep '__GNUC__' +``` + +#### 解决方案 + +若宏内容不一致导致报错,可以在编译选项加入 `-D__GNUC__=x` 进行适配修改。 + +### 支持的 Attributes 集合 + +LLVM for openEuler 只支持 Clang 框架中的 attributes,请参考[clang文档](https://clang.llvm.org/docs/AttributeReference.html)。 + +链接中未提到 attributes 暂不支持。 + +### -march 选项在架构扩展特性上的使用说明 + +Clang 使用架构扩展特性时,需在 `-march=` 后加上扩展特性的名称,包括架构默认支持的扩展特性。例如,DotProd 特性是 Armv8.4 架构默认支持的,可使用 `-march=armv8.4-a+dotprod` 使能该特性。 + +### -mgeneral-regs-only 选项的使用说明 + +使用该选项时将生成仅使用通用寄存器的代码,这会阻止编译器使用浮点或高级 SIMD 寄存器。因此当编译时加入该选项,编译器应避免使用浮点运算指令,如果程序中有浮点运算,LLVM for openEuler 将会调用 compiler-rt 中的库函数进行运算。因此,链接时要配合添加 `-rtlib=compiler-rt -l gcc_s` 选项。 + +### Hardware-assisted AddressSanitizer 仅支持在基于 Linux5.4 及以上内核版本的 OS 上运行 + +Hardware-assisted AddressSanitizer 可以通过 `-fsanitize=hwaddress -fuse-ld=lld` 使能,该特性依赖一部分 Linux5.4 及以上才支持的内核接口,若环境内核版本低于 5.4 则无法正常使能,这种情况下建议使用常规地址消毒。 + +### Neon Intrinsic + +Neon Intrinsic 和编译器的具体实现相关,Clang 的neon Intrinsic 的功能与官方文档[《Arm Neon Intrinsics Reference》](https://developer.arm.com/documentation/ihi0073/g)(以下简称ANIR文档)一致。 + +但生成 ANIR 文档上指定的汇编指令,需指定优化级别大于 O0。 + +#### 使用举例 + +以内容如下的test.c为例: + +```c +#include +int32x2_t test_vsudot_lane_s32(int32x2_t r, int8x8_t a, uint8x8_t b) { + return vsudot_lane_s32(r, a, b, 0); +} +``` + +表1 ANIR文档上vsudot_lane_s32的描述 + +| Intrinsic | Argument Preparation | Instruction | Result |Supported Architectures | +|-|-|-|-|-| +| int32x2_t vsudot_lane_s32(int32x2_t r, int8x8_t a, uint8x8_t b, const int lane) | r -\> Vd.2S
a -\> Vn.8B
b -\> Vm.4B
0 \<= lane \<= 1 | SUDOT Vd.2S,Vn.8B,Vm.4B[lane] | Vd.2S -\> result | A32/A64 | + +使用命令 `clang -march=armv8.6-a+i8mm test.c -O0 -S` 生成的结果是以 mov、dup 和 usdot 等多条指令组合的形式。 + +```asm +test_vsudot_lane_s32: // @test_vsudot_lane_s32 +// %bb.0: // %entry + sub sp, sp, #112 // =112 + str d0, [sp, #72] + str d1, [sp, #64] + str d2, [sp, #56] + ldr d0, [sp, #72] + str d0, [sp, #48] + ldr d0, [sp, #64] + str d0, [sp, #40] + ldr d0, [sp, #56] + str d0, [sp, #32] + ldr d0, [sp, #32] + str d0, [sp, #16] + ldr d0, [sp, #48] + ldr d1, [sp, #16] + // implicit-def: $q3 + mov v3.16b, v1.16b + dup v1.2s, v3.s[0] + ldr d2, [sp, #40] + str d0, [sp, #104] + str d1, [sp, #96] + str d2, [sp, #88] + ldr d0, [sp, #104] + ldr d1, [sp, #96] + ldr d2, [sp, #88] + usdot v0.2s, v1.8b, v2.8b + str d0, [sp, #80] + ldr d0, [sp, #80] + str d0, [sp, #24] + ldr d0, [sp, #24] + str d0, [sp, #8] + ldr d0, [sp, #8] + add sp, sp, #112 // =112 + ret +``` + +使用命令 `clang -march=armv8.6-a+i8mm test.c -O1 -S` 生成结果与 ANIR 文档一致。 + +```asm +test_vsudot_lane_s32: // @test_vsudot_lane_s32 +// %bb.0: // %entry + // kill: def $d2 killed $d2 def $q2 + sudot v0.2s, v1.8b, v2.4b[0] + ret +``` + +## OpenMP兼容性 + +### linear 子句和 chucked dynamic schedule 子句共用不支持 + +当 `linear` 子句和 `chucked dynamic schedule` 子句一起使用时,OpenMP 不支持该场景的线程调度,导致运行后循环的线性变量的值不正确。 + +该场景已提交到[上游社区](https://github.com/llvm/llvm-project/issues/61230),等待社区进行修复。 + +规避方案是可以使用其它子句来替换,或者不使用 `chucked dynamic schedule` 的线程调度方式。 + +### Omp atomic 特性依赖 10.3.0 及以上的系统 GCC 版本 + +Omp atomic 特性依赖系统 GCC 的 libgcc,低于 10.3.0 的系统 GCC 版本可能引发运行结果异常。如果需要使用请保证系统 GCC 版本满足要求。使用 Omp atomic 特性的具体用例如下: + +```c +void foo(double *Ptr, double M, double N) { + double sum = 0; + #pragma omp parallel for + for (int i = 0; i < 100; ++i){ + Ptr[i] = i+(M*2 + N); + #pragma omp atomic + sum += Ptr[i]; + } +} +``` + +## 问题反馈 + +在使用过程中遇到问题,需要技术支持时,请反馈问题信息至 openEuler 社区 [llvm-project](https://gitee.com/openeuler/llvm-project) 源码仓。 diff --git a/docs/zh/llvm/kernel_pgo_user_guide.md b/docs/zh/llvm/kernel_pgo_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..39f558c3255476df2b69400fe9826710d837e32d --- /dev/null +++ b/docs/zh/llvm/kernel_pgo_user_guide.md @@ -0,0 +1,84 @@ +# 内核反馈优化特性 + +## 简介 + +[PGO(Profile-Guided Optimization)](https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization)是一种编译器反馈优化技术,通过收集程序运行时的信息,指导编译器的优化决策。内核反馈优化(PGO kernel)特性为内核提供了反馈优化能力的支持,使用户可以为不同的应用程序构建针对性优化的内核,在单应用场景下提高目标应用的性能。根据业界经验,对于数据中心大型应用(如MySQL、Nginx、Redis等)通过PGO优化应用和内核有较好的效果。 + +## 环境准备 + +### 软件要求 + +* 操作系统:openEuler 24.03 LTS (SP1) +* clang、llvm、lld:17.0.6 + +### 硬件要求 + +* AArch64架构 +* x86_64架构 + +### 安装软件 + +安装内核源码、编译工具链及其他依赖包: + +```bash +yum install -y kernel-source clang llvm lld flex bison rpm-build elfutils-libelf-devel dwarves openssl-devel rsync +``` + +复制内核源码: + +```bash +cp -r /usr/src/linux-6.6.0-54.0.0.57.oe2403.aarch64 . +``` + +> [!WARNING]注意 \ +> 具体版本号可能有变化。 + +## 使用方法 + +和一般的插桩式反馈优化类似,这里也先构建一个插桩版本,使用编译器插入的探针收集运行时信息并写入到文件,使用收集到的文件二次构建,指导编译器的优化决策。 + +### 插桩版本构建 + +```bash +make LLVM=1 LLVM_IAS=1 openeuler_defconfig +scripts/config -e PGO_CLANG +make LLVM=1 LLVM_IAS=1 binrpm-pkg -j$(getconf _NPROCESSORS_ONLN) +``` + +### 安装插桩版本内核并重启 + +```bash +rpm -ivh kernel-6.6.0-1.aarch64.rpm # 注意文件名可能不同 +grub2-reboot 0 # 指定下一次重启的启动项为刚安装的内核 +reboot +``` + +### 收集profile信息 + +重置数据: + +```bash +echo 1 > /sys/kernel/debug/pgo/reset +``` + +运行程序后,获取采集到的profile信息: + +```bash +cp -a /sys/kernel/debug/pgo/vmlinux.profraw /tmp/vmlinux.profraw +llvm-profdata merge /tmp/vmlinux.profraw -o vmlinux.profdata +``` + +### 二次构建 + +```bash +make LLVM=1 LLVM_IAS=1 openeuler_defconfig +make LLVM=1 LLVM_IAS=1 KCFLAGS=-fprofile-use=/the/profile/data/path/vmlinux.profdata binrpm-pkg -j$(getconf _NPROCESSORS_ONLN) +``` + +### 安装优化版本内核并重启 + +```bash +rpm -ivh kernel-6.6.0-2.aarch64.rpm +grub2-reboot 0 +reboot +``` diff --git a/docs/zh/llvm/llvm_pgo_user_guide.md b/docs/zh/llvm/llvm_pgo_user_guide.md new file mode 100644 index 0000000000000000000000000000000000000000..225ed46d1b03c58c0a812800ab166b6a5222ec57 --- /dev/null +++ b/docs/zh/llvm/llvm_pgo_user_guide.md @@ -0,0 +1,80 @@ +# LLVM 反馈优化特性 + +## PGO 简介 + +PGO(Profile-Guided Optimization)是一种编译器优化技术。它通过在程序运行时收集性能数据,并在编译阶段使用这些数据来优化程序的性能。PGO 需要两次编译过程,第一次编译时在应用代码中插桩,通过运行典型用例和业务,收集应用代码中函数及分支的执行次数信息,第二次编译时根据运行统计信息近一步优化,生成高性能应用。PGO 等反馈优化技术在数据库、分布式存储等数据和计算密集型等前端瓶颈较高的场景效果显著,性能可提升 10%~30%。它能够有效减少计算时间和资源消耗,提升应用性能,显著降低运营成本并提高用户体验。 + +![alt text](figures/figure_pgo_0.png) + +## 优化原理 + +传统编译优化只能通过静态的程序分析及启发式算法预测程序的执行行为。PGO 通过采集程序运行时信息,可以精准的判断代码的冷热、执行的概率,从而完成高效的冷热分区、分支预测、函数重排、寄存器分配、向量化、函数内联等优化,提升 cache 命中率、分支命中率和数据并行度,减少寄存器压力。 + +典型优化原理说明如下: + +1. 冷热分区 + + 剥离冷分支,使热点代码聚合,提升 cache 命中率。 + + ![alt text](figures/figure_pgo_1.png) + +2. 函数重排 + + 代码段函数重排,使热点函数聚合,降低 iTLB 及 icache miss。 + + ![alt text](figures/figure_pgo_2.png) + +3. 分支预测 + + 调整分支顺序,降低 branch miss 率。 + + ![alt text](figures/figure_pgo_3.png) + +4. 函数内联 + + 基于反馈的 inline:全局分析,精准内联,优化调用栈,内存排布更优。 + + ![alt text](figures/figure_pgo_4.png) + +5. switch优化 + + 结构分支调整,减少跳转,降低 branch miss 率。 + + ![alt text](figures/figure_pgo_5.png) + +## 优化效果 + +数据库场景:MySQL、GaussDB 等数据库应用,使用 LLVM LTO+PGO 优化,性能提升 20%~30%。 + +分布式存储:Ceph、LAVA 等分布式存储解决方案,使用 LLVM LTO+PGO 优化,性能提升 10%+。 + +## 使用方法 + +1. 增加编译选项 `-fprofile-generate=$PROFILE_DATA_PATH`(`$PROFILE_DATA_PATH` 为用于存放采样文件的路径)编译源码得到可执行文件。 + +2. 给可执行文件一组有代表性的输入,并运行可执行文件进行采样,采样后在 `$PROFILE_DATA_PATH` 路径下会得到 `xxxx.profraw` 采样文件。 + +3. `cd $PROFILE_DATA_PATH`,使用下述命令处理采样文件,得到优化指导文件(`.profdata`): + + ```shell + $LLVM_DIR/bin/llvm-profdata merge -output=foo.profdata ./*.profraw #$LLVM_DIR表示编译器路径 + ``` + +4. 增加选项 `-fprofile-use=$PROFILE_DATA_PATH/foo.profdata` 编译源码得到优化后的可执行文件。 + +## 注意事项 + +1. 插桩之后的运行阶段,程序需要正常结束才能正常生成采样文件,直接 `kill -9` 不能正常生成采样文件。 + +2. 如果程序无法正常退出,可以尝试以下方法生成 profile。(以 MySQL 为例) + + ```shell + echo "set height 0" > gdb.cmd + echo "handle SIGPIPE SIGUSR1 SIGUSR2 SIG36 noprint nostop" >> gdb.cmd + echo "call (void)__llvm_profile_write_file()" >> gdb.cmd + echo "detach" >> gdb.cmd + echo "q" >> gdb.cmd + gdb -x gdb.cmd -p `pidof mysql` # mysql 对应具体采样进程 + ``` + +3. 在[使用方法](#使用方法)步骤 3 中 merge profile 时,如果出现 `counter overflow` 的错误提示,可以通过增加环境变量 `LLVM_PROFILE_FILE=$PROFILE_DATA_PATH/code-%p`,按照每个进程生成采样文件,减少进程间耦合导致采样异常的问题。 diff --git a/docs/zh/llvm/more_architecture_supported.md b/docs/zh/llvm/more_architecture_supported.md new file mode 100644 index 0000000000000000000000000000000000000000..72b2a09fd53839cba4ae67c469087a83088c0bb2 --- /dev/null +++ b/docs/zh/llvm/more_architecture_supported.md @@ -0,0 +1,10 @@ +# 新增架构支持 + +LLVM for openEuler 支持通过 `-mcpu=` 选项指定当前的 cpu 型号,使能该 cpu 所有默认特性。在使能对应的微架构亲和选项后,LLVM for openEuler 会依据对应架构的指令实现进行指令流水线调优,提升性能。硬件平台与该选项的配置项对应关系如下: + +|硬件平台|配置项| +|-|-| +|鲲鹏920|tsv110| +|HiSilicon Hip09|hip09| +|HiSilicon Hip10c|hip10c| +|HiSilicon Hip11|hip11|