From cfc9f5c8d3b62bc089867e9de817d4cfa8c79fd7 Mon Sep 17 00:00:00 2001 From: zwiori Date: Wed, 6 Aug 2025 11:17:57 +0800 Subject: [PATCH] update comilation related md --- .../features/compile/compilation_guide.md | 459 ++++++++++++++++++ .../features/compile/graph_construction.md | 181 ------- .../features/compile/graph_optimization.md | 318 ------------ .../features/compile/images/graphkernel.png | Bin 0 -> 23883 bytes .../images/graphkernel_akg_overview.png | Bin 0 -> 217579 bytes .../compile/multi_level_compilation.md | 137 ------ docs/mindspore/source_en/features/overview.md | 16 +- ...ptimization.md => compilation_guide_zh.md} | 273 ++++++++--- .../features/compile/graph_construction.ipynb | 273 ----------- .../compile/multi_level_compilation.md | 139 ------ .../source_zh_cn/features/overview.md | 20 +- 11 files changed, 679 insertions(+), 1137 deletions(-) create mode 100644 docs/mindspore/source_en/features/compile/compilation_guide.md delete mode 100644 docs/mindspore/source_en/features/compile/graph_construction.md delete mode 100644 docs/mindspore/source_en/features/compile/graph_optimization.md create mode 100644 docs/mindspore/source_en/features/compile/images/graphkernel.png create mode 100644 docs/mindspore/source_en/features/compile/images/graphkernel_akg_overview.png delete mode 100644 docs/mindspore/source_en/features/compile/multi_level_compilation.md rename docs/mindspore/source_zh_cn/features/compile/{graph_optimization.md => compilation_guide_zh.md} (33%) delete mode 100644 docs/mindspore/source_zh_cn/features/compile/graph_construction.ipynb delete mode 100644 docs/mindspore/source_zh_cn/features/compile/multi_level_compilation.md diff --git a/docs/mindspore/source_en/features/compile/compilation_guide.md b/docs/mindspore/source_en/features/compile/compilation_guide.md new file mode 100644 index 0000000000..e77411ba7f --- /dev/null +++ b/docs/mindspore/source_en/features/compile/compilation_guide.md @@ -0,0 +1,459 @@ +# mindspore.jit Multi-Level Compilation Optimization + +[![View Source](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/mindspore/source_en/features/compile/compilation_guide.md) + +## MindSpore Compilation Architecture + +MindSpore utilizes jit (just-in-time) for performance optimization. The jit mode converts Python code to intermediate representation graphs (IR, Intermediate Representation) through AST tree parsing, Python bytecode parsing, or code execution tracing. We name it MindIR. The compiler optimizes this IR graph to achieve code optimization and improve runtime performance. In contrast to dynamic graph mode, this JIT compilation mode is called graph mode. + +Python code written by developers runs in dynamic graph mode by default. Functions can be decorated with the @mindspore.jit decorator to specify execution in graph mode. For documentation on the @mindspore.jit decorator, please refer to the [jit documentation](https://www.mindspore.cn/docs/en/master/api_python/mindspore/mindspore.jit.html). + +Graph mode is roughly divided into 3 stages: + - Graph Capture (Graph Construction): python code -> MindIR. + - Graph Optimization (Frontend): Hardware-independent optimization of MindIR, algebraic simplification, function inlining, redundancy elimination, etc. + - Graph Optimization (Backend): Hardware-dependent optimization of MindIR, LazyInline, operator selection, graph-operator fusion, etc. + +## Graph Capture (Graph Construction) + +MindSpore provides three capture methods as follows: + - AST: Converts executed functions to IR graphs through AST tree parsing + - bytecode (experimental): Parses Python bytecode to construct IR graphs as much as possible. Parts that cannot be converted to IR graphs will be executed according to dynamic graph + - trace (experimental): Constructs IR graphs by tracing the execution trajectory of Python code + + + Taking ast as an example: developers can choose `@mindspore.jit:(capture_mode="ast")` decorator to modify functions. Functions modified with ast mode have certain syntax restrictions. We provide two modes for developers to choose from. + + - strict mode: The goal of this mode is to construct a single graph. If the developer's Python code cannot construct a graph, choosing this mode will cause an error when running the program, requiring the developer to modify the code to use graphable syntax. This is suitable for developers pursuing performance. + - lax mode: The goal of this mode is to make the developer's program runnable as much as possible. The idea is to perform Python fallback for code that cannot construct graphs in strict mode, that is, return to the Python layer for execution. + +For graph mode constraints, please refer to [Syntax Constraints](https://www.mindspore.cn/tutorials/en/master/compile/static_graph.html). Here's an example of how ast parses Python code and constructs graphs: + +```python +@mindspore.jit +def foo(x, y): + z = x + y + return z +``` + +The corresponding abstract syntax tree is as follows: + +![Abstract Syntax Tree](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/docs/mindspore/source_zh_cn/features/compile/images/ast.png) + +By parsing the above abstract syntax tree, we obtain the following IR: + +```text +%para1_x: +%para2_y: + +subgraph instance: foo +subgraph @foo() { + %0(CNode_17) = PrimFunc_Add(%para1_x, %para2_y) + : (, ) -> () + Return(%0) + : () +} +``` + +**Advantages of ast**: + + - Using ast mode gives users stronger programming autonomy and more precise performance optimization. They can tune network performance to optimal based on function characteristics and usage experience. + +**Limitations of ast**: + + - Functions decorated with ast must strictly follow static graph syntax for internal programming. + +**recommendations for ast mode**: + - Compared to dynamic graph execution, functions decorated with `@mindspore.jit` need to consume certain time for compilation on the first call. In subsequent calls to this function, if the original compilation result can be reused, the original compilation result will be used directly for execution. Therefore, using the `@mindspore.jit` decorator to modify functions that will be executed multiple times usually obtains more performance benefits. + + - The runtime efficiency advantage of graph mode is reflected in its global compilation optimization of functions decorated with `@mindspore.jit`. The more operations contained in the function, the greater the optimization space. Therefore, functions decorated with `@mindspore.jit` are best large code blocks containing many operations, rather than many fragmented functions containing only a few operations separately marked with jit tags. Otherwise, it may lead to no performance benefits or even degradation. + + - Most calculations and optimizations are based on optimization of Tensor calculations. It is recommended that decorated functions should be used for real data calculation functions, rather than simple scalar calculations or data structure transformations. + + - For functions decorated with `@mindspore.jit`, if their inputs contain constants, changes in input values each time will cause recompilation. For the concept of variable constants, please refer to [Constants and Variables in Just-in-Time Compilation](https://www.mindspore.cn/tutorials/en/master/compile/static_graph.html). Therefore, it is recommended that decorated functions take Tensors or data modified by Mutable as input to avoid additional performance loss caused by multiple compilations. + +## Graph Optimization (Frontend) + +Similar to traditional compilation optimization techniques, compilation optimization in MindSpore is also completed through individual Passes. Each Pass takes the MindIR produced by the previous Pass as input, and after optimization by this Pass, produces a new MindIR representation as output. A large Pass can contain multiple small Passes, each small Pass is only responsible for single-point compilation optimization, such as: algebraic simplification, function inlining, redundancy elimination, etc. The optimization result produced by one Pass may bring optimization opportunities for other Passes, so these Passes can be run in cycles until the produced MindIR no longer changes. + +There are many frontend compilation optimization techniques, such as: algebraic simplification, function inlining, redundancy elimination, etc. Here we only introduce representative compilation optimization techniques. + +### 1 Algebraic Simplification + +In traditional compilers, algebraic simplification is a compiler optimization technique aimed at simplifying algebraic expressions in source code, eliminating redundant calculations, improving program execution efficiency, and reducing memory usage. +For example, in the following code snippet: + +```cpp +int a = x * 1; +int b = x + 0; +int c = x * 0 + y * 1; +``` + +Traditional compilers perform equivalent replacement of identified expressions according to algebraic rules and identities. Common algebraic rules include associative law, commutative law, and distributive law, etc. The compiler tries to replace expressions with simpler forms as much as possible. Optimization is performed through analysis of AST (Abstract Syntax Tree) or SSA (Static Single Assignment), identifying and simplifying code to: + +```cpp +a = x; +b = x; +c = y; +``` + +In the MindSpore compiler, the principle of algebraic simplification is different from traditional compilers. It processes computation graphs rather than traditional control flow graphs, by adjusting the execution order of operators in the computation graph, or deleting unnecessary operators, to maintain the simplicity of the computation graph and improve computational efficiency. + +For example, in the following Python code snippet: + +```python +import numpy as np +import mindspore + +@mindspore.jit +def func(x): + return x + 0 + +m = mindspore.tensor(np.array([[1, 2, 3], [4, 5, 6]]).astype(np.int32)) +out = func(m) +``` + +The MindSpore graph compiler will convert the Python program to a computation graph, which consists of multiple subgraphs. Algebraic operations in the source program are converted to operator calls within subgraphs. You can see that the PrimFunc_Add operator is called once. + + +```text +%para1_x: + +subgraph @1_func_14() { + %0(CNode_7) = PrimFunc_Add(%para1_x, Tensor(shape=[], dtype=Int32, value=0)) + : (, ) -> () + + Return(%0) + : () +} +``` + +Through algebraic simplification, the PrimFunc_Add operator can be directly deleted, simplifying the computation graph structure, and simplifying x + 0 to x. + + +```text +%para1_x: + +subgraph @1_func_14() { + Return(%para1_x) + : () +} +``` + +Algebraic simplification can involve more modifications to the computation graph structure. It is usually combined with other compiler optimization techniques (such as constant folding, constant propagation, etc.) to jointly improve program performance. + +### 2 Function Inlining + +In traditional compilers, inlining is an optimization technique that can directly replace the code of called functions at the location where the function is called, improving program execution efficiency. Suppose we have a C++ function add for summing two numbers: + +```cpp +int add(int a, int b) { + return a + b; +} + +int main() { + int x = add(3, 5); + int y = add(x, 10); + return y; +} +``` + + +The compiler inlines the function body directly to the call site, which eliminates the overhead of function calls and creates conditions for subsequent optimizations (such as eliminating redundant calculations 3 + 5, directly evaluating and replacing at compile time). This idea of replacing calls with code is the core of inlining. + +```cpp +int main() { + int x = 3 + 5; // Replace first call + int y = x + 10; // Replace second call + return y; +} +``` + +In AI framework computation graph compilers, the goal of inlining is similar, but the operation object changes from "functions" to "subgraphs". Suppose we have a Python program: + +```python +from mindspore + +def f2(x: mindspore.Tensor, y: mindspore.Tensor): + return x * 0.5 + y + +@mindspore.jit +def f1(a: mindspore.Tensor, b: mindspore.Tensor, c: mindspore.Tensor): + x = f2(a, b) + y = f2(a, c) + return x + y + +# Create 3 random value Tensors with shape=(2, 4) +a = mindspore.ops.randn(2, 4) +b = mindspore.ops.randn(2, 4) +c = mindspore.ops.randn(2, 4) +out = f1(a, b, c) +``` + + +First, MindSpore's computation graph compiler will convert the Python program to a computation graph. Function calls in the Python program will be converted to calls between computation graphs, resulting in an original computation graph similar to the following. Among them, the main graph f1 calls the subgraph f2 twice. + + +```text +# Params: +%para1_a: +%para2_b: +%para3_c: + +subgraph @f2(%para1_x, %para2_y) { + %0 = PrimFunc_Mul(%para1_x, Float32(0.5)) + + %1 = PrimFunc_Add(%0, %para2_y) + + Return(%1) +} + +subgraph @f1() { + %0(x) = call @f2(%para1_a, %para2_b) # Call subgraph f2 + + %1(y) = call @f2(%para1_a, %para3_c) # Call subgraph f2 + + %2 = PrimFunc_Add(%0, %1) + + Return(%2) +} +``` + +Through inlining, the subgraph f2 can be expanded and merged into the main graph f1. + +```text +subgraph @f1() { + # First subgraph inlining + %0 = PrimFunc_Mul(%para1_a, Float32(0.5)) # Repeated calculation step + %1 = PrimFunc_Add(%0, %para2_b) + + # Second subgraph inlining + %2 = PrimFunc_Mul(%para1_a, Float32(0.5)) # Repeated calculation step + %3 = PrimFunc_Add(%2, %para3_c) + + %4 = PrimFunc_Add(%1, %3) + + Return(%4) +} +``` + +Before inlining expands the subgraph, the compiler may not be able to identify the repeated operations in the two calls to subgraph f2 (at this time the subgraph is usually treated as a black box). After inlining expands the subgraph, the compiler can clearly see that x * 0.5 is calculated twice, which can trigger further optimization by the compiler: Common Subexpression Elimination (CSE), thus reducing the amount of calculation. + +```text +subgraph @f1() { + %0 = PrimFunc_Mul(%para1_a, Float32(0.5)) # CSE merges repeated calculations + + %1 = PrimFunc_Add(%0, %para2_b) + + %2 = PrimFunc_Add(%0, %para3_c) # Directly reuse %0 + + %3 = PrimFunc_Add(%1, %2) + + Return(%3) +} +``` + +By inlining to expand subgraphs, the compiler can more clearly identify cross-subgraph optimization opportunities. In addition to Common Subexpression Elimination (CSE), it can also trigger many optimization measures such as operator fusion and memory management. Therefore, inlining is an important optimization mechanism in computation graph compilers and the foundation for many cross-graph optimizations. + +### 3 Redundancy Elimination + +In traditional compilers, redundancy elimination includes various compilation optimization techniques aimed at identifying redundant parts in code during compilation and eliminating them to reduce unnecessary calculations and improve program execution efficiency. + +Usually redundant code may be intentionally written by users for readability purposes, or it may just be an unintentional act during the coding process. In addition, intermediate results produced by the compilation optimization process itself through other optimization techniques (such as: algebraic simplification, inlining, common subexpression elimination, etc.) may also bring opportunities for redundancy elimination. + +The purpose and techniques used in MindSpore redundancy elimination are similar to traditional compilers. The difference is that these redundancy optimizations are completed on MindIR. For example: + +1. **Dead Code Elimination** + + Suppose there is Python code with redundant calculations as follows: + + ```python + import mindspore + + @mindspore.jit + def func(x, y): + a = x + y + b = x - y + c = x * y # Dead code + d = a / b + return d + + x = mindspore.tensor(20, mindspore.float32) + y = mindspore.tensor(10, mindspore.float32) + out = func(x, y) + ``` + +The MindSpore graph compiler will convert Python code decorated with `@mindspore.jit` to MindIR representation through static analysis and eliminate the redundant calculation of c = x * y. The final generated MindIR is as follows: + + ```text + # Params: + %para1_x: + %para2_y: + + subgraph @func_1() { + %0(a) = PrimFunc_Add(%para1_x, %para2_y) + : (, ) -> () + %1(b) = PrimFunc_Sub(%para1_x, %para2_y) + : (, ) -> () + %2(d) = PrimFunc_Div(%0, %1) + : (, ) -> () + Return(%2) + : () + } + ``` +2. **Unreachable Code Elimination** + + Suppose there is Python code with unreachable paths as follows: + + ```python + import mindspore + + @mindspore.jit + def func(x, y): + a = x + y + if 1 < 0: # Unreachable branch + b = x + y + else: + b = x - y + d = a / b + return d + + x = mindspore.tensor(20, mindspore.float32) + y = mindspore.tensor(10, mindspore.float32) + out = func(x, y) + ``` + +The MindSpore graph compiler will convert Python code decorated with `@mindspore.jit` to MindIR representation through static analysis and eliminate the redundant control flow branch code of `1 < 0`. The final generated MindIR is as follows: + + ```text + # Params: + %para1_x: + %para2_y: + + subgraph @func_1() { + %0(a) = PrimFunc_Add(%para1_x, %para2_y) + : (, ) -> () + %1(b) = PrimFunc_Sub(%para1_x, %para2_y) + : (, ) -> () + %2(d) = PrimFunc_Div(%0, %1) + : (, ) -> () + Return(%2) cnode_attrs: {checkpoint: Bool(1)} + : () + } + ``` + +Redundancy elimination plays an important role in compilation optimization. Without changing the original semantics of the program, it can significantly improve program execution efficiency and save computational resources by reducing unnecessary runtime calculations. Redundancy elimination is usually combined with other compilation optimization techniques to obtain more opportunities for eliminating redundant code. + +## Graph Optimization (Backend) +After the MindIR graph completes frontend optimization, it needs further optimization (including target hardware). The optimization modes are divided into O0 and O1, represented by the parameter jit_level: + - **jit_level=O0**: Only performs basic graph segmentation optimization and operator selection (hardware-related). The advantage is that it can guarantee the original structure of the IR graph and has faster compilation speed. + - **jit_level=O1**: Adds graph optimization and automatic operator fusion. Compilation performance is somewhat lost, but after the model starts training, efficiency is higher. + +After this round of optimization, MindIR will be executed by the runtime module, involving multi-level pipeline concurrency and other technologies. For reference, see [Multi-Level Pipeline]. + +### jit_level=O0 Mode + +O0 mode has fewer optimizations. The basic optimizations are mainly backend LazyInline and No-task node execution optimization. + + - ***LazyInline**: The main idea is to postpone the overhead of function calls to when they are actually needed, which can reduce compilation overhead and improve compilation efficiency. LazyInline reuses the same subgraph structure during the graph compilation phase without expanding it in the graph, avoiding large graph scale affecting compilation performance. + + ![jit_level_lazyinline](./images/multi_level_compilation/jit_level_lazyinline.png) + + - **No-task node Execution Optimization**: No-task nodes refer to operators such as Reshape, ExpandDims, Squeeze, Flatten, FlattenGrad, Reformat, etc. These operators have no computational logic, do not modify memory layout, and only modify shape, format and other information. At the end of graph compilation, No-task nodes are converted to ref nodes, where the output has the same address as the input, and kernel launch is skipped during execution to achieve execution performance optimization. + + ![jit_level_no_task](./images/multi_level_compilation/jit_level_no_task.png) + +#### Operator Selection + +Operators are the basic execution units in deep learning frameworks. They are responsible for performing specific computational tasks such as matrix multiplication, convolution, pooling, etc. Operator selection requires comprehensive consideration of factors such as operator type, data type, hardware platform, and operator optimization to select the optimal operator for achieving the highest model runtime efficiency. + +MindSpore's operator types on Ascend hardware are aclnn kernel/aclop kernel/hccl kernel/cpu kernel. The operator selection process is shown in the following figure: + +![jit_level_kernelselect](./images/multi_level_compilation/jit_level_kernelselect.png) + +1. Operator type: First, according to the operator type, choose whether it is a computational operator or communication operator. +2. Hardware platform: If there is a corresponding operator on the hardware, the operator on the hardware is preferred, otherwise the operator on CPU is chosen (heterogeneous). For example, shape-related computational operators may only be suitable to be supported on CPU, and there is no corresponding hardware operator. +3. Operator efficiency: Due to the better performance of aclnn operators on Ascend hardware, computational operators will prefer aclnn kernel if there is a corresponding aclnn kernel, otherwise aclop kernel will be chosen. +4. If no operator is selected in any of the above 3 steps, it is an unsupported operator and operator selection fails with an error. + +#### Execution Order Scheduling + +Different graph traversal algorithms produce execution orders with large differences in execution performance and memory, as shown in the figure: + +![jit_level_exec_order](./images/multi_level_compilation/jit_level_exec_order.png) + + - **Execution order obtained by BFS**: kernel1-> kernel2-> kernel4-> kernel5-> kernel3-> kernel6, memory peaks at 5G (kernel3 can release kernel1 and kernel2 after execution, then reuse them when it's kernel6's turn to execute, so kernel6 doesn't need to request extra memory). + - **Execution order obtained by DFS**: kernel1-> kernel2-> kernel3-> kernel4-> kernel5-> kernel6, memory peaks at 4G (kernel3 can release kernel1 and kernel2 after execution, then reuse them when it's kernel4 and kernel5's turn to execute, so kernel4 and kernel5 don't need to request extra memory). + +Execution order scheduling is a complex problem of solving optimal operator concurrency under certain memory constraints. It not only requires identifying and exploiting concurrency opportunities in the computational graph to improve computational efficiency, but also must consider multiple constraints simultaneously to ensure system stability and efficiency. + + - First, the optimization module needs to address the complexity of solving for optimal operator concurrency. Due to the large number of operators in the computational graph and their interdependencies, finding an execution order that maximizes concurrency while maintaining the logical correctness of the computational graph is a challenging task. + + - Second, memory constraints are a critical factor that cannot be ignored in execution order optimization. Increasing concurrency, while improving computational efficiency, tends to significantly increase peak memory requirements, which may lead to Out of Memory (OOM) errors, especially in resource-constrained environments. Therefore, the optimization module must weigh the relationship between concurrency and memory usage to ensure that concurrency is increased without exceeding the memory capacity of the system. + + - MindSpore's execution order adjustment module combines rule-based and heuristic-based strategies to provide both bfs/dfs execution order orchestration algorithms [mindspore.jit(option={"exec_order":"bfs/dfs"})](https://www.mindspore.cn/docs/zh-CN/master/api_python/mindspore/mindspore.jit.html) to achieve fine-grained adjustment of the execution order of the computation graph, thus effectively dealing with multiple challenges such as memory constraints and system stability while ensuring computational efficiency. + +### jit_level=O1 Mode + +Currently O1 mainly supports graph-operator fusion optimization. The main idea is: during the compilation phase, automatically identify neighboring fusable nodes in the computational graph, then fuse them into executable operators with larger granularity. Through graph-operator fusion, optimization effects such as increasing operator computational locality and reducing overall global memory access bandwidth overhead are achieved. Through real-world testing verification on mainstream SOTA models, O1 can achieve an average 15% performance acceleration compared to O0. Especially for memory access-intensive networks, the optimization effect of O1 is more significant. + +#### Graph-Kernel Fusion + +Mainstream AI computing frameworks such as MindSpore provide operators to users that are usually defined from the perspective of user understanding and ease of use. Each operator carries different amounts of computation and varies in computational complexity. However, from the hardware execution perspective, this natural, user perspective-based division of operator computation volume is not efficient and cannot fully utilize the computational power of hardware resources. This is mainly reflected in: + +1. Operators with too much computation and overly complex operators usually make it difficult to generate well-split high-performance operators, thereby reducing device utilization; + +2. Operators with too little computation may also cause computational latency and thus reduce device utilization, as the computation cannot effectively hide data movement overhead; + +3. Hardware devices are usually multi-core, many-core architectures. When operator shapes are small or other reasons cause insufficient computational parallelism, it may cause some cores to be idle, thus reducing device utilization. Especially chips based on Domain Specific Architecture (DSA for short) are more sensitive to these factors. How to maximize hardware computational performance while making operators easy to use has always been a big challenge. + +In terms of AI framework design, the current industry mainstream adopts a layered implementation approach of graph layer and operator layer. The graph layer is responsible for fusing or regrouping the computational graph, and the operator layer is responsible for compiling the fused or regrouped operators into high-performance executable operators. The graph layer usually uses Tensor-based High-Level IR for processing and optimization, while the operator layer uses computation instruction-based Low-Level IR for analysis and optimization. This artificial layered processing significantly increases the difficulty of collaborative optimization between the graph and computation layers. + +MindSpore has adopted the technique of graph-operator fusion to better solve this problem in the past few years of technical practice. Typical networks in different categories such as NLP and recommendation show significant gains in training speed after enabling graph-operator fusion. One of the main reasons is the presence of a large number of small operator combinations in these networks, which have more opportunities for fusion optimization. + +#### Graph-Kernel Fusion Architecture and Overall Process + +The overall architecture of graph-operator fusion is shown in the figure below. The main idea in the graph layer is to expand composite operators, then perform cross-boundary aggregation and optimization, and finally perform kernel operator splitting. The main steps include: + +1. Composite Expansion: Expand composite operators into basic operators and form composite subgraphs to facilitate subsequent cross-boundary optimization and operator splitting; + +2. Cross-OP Aggregation: Aggregate adjacent basic operators or composite subgraphs to form larger aggregated subgraphs for subsequent cross-boundary optimization and operator splitting; + +3. High-Level Optimization: Based on the aggregated subgraphs obtained in the above two steps, we can perform a large number of cross-boundary optimizations, such as algebraic simplification, common subexpression extraction (CSE), etc.; + +4. Kernel Partition: Based on computational features and fusion operator performance, perform operator splitting on the aggregated computational subgraph. + +The optimized computational graph is passed to MindSpore AKG as subgraphs for further backend optimization and target code generation. + +![graphkernel](./images/graphkernel.png) + +Through the above steps, we can obtain two aspects of performance gains: +1. Cross-boundary performance optimization gains between different operators; +2. Through reorganization and splitting of the entire computational graph, the optimal granularity of fusion operators is obtained. + +#### Fusion Operator Acceleration Optimization (MindSpore AKG) + +As mentioned earlier, in scenarios such as HPC and deep neural network training, graph-operator fusion optimization can bring exponential performance improvements. However, with the increasing capability of graph-operator fusion, the development of fusion operators has become a bottleneck point for continuing to improve graph-operator fusion capability. + +Automatic generation technology of fusion operators can solve the problem of high programming threshold for developing fusion operators based on DSA, allowing programmers to focus on operator implementation logic during operator development without focusing on backend optimization, greatly improving their development efficiency. Especially for scenarios with complex backend hardware architectures and the presence of complex operators and fusion operators, automatic operator generation technology is more critical. + +Therefore, **MindSpore AKG accelerates optimization and automatic generation of fusion operators based on Polyhedral Compilation Technology (Polyhedral Model)**, which can help fusion operators optimized by MindSpore's graph-operator fusion module to automatically generate high-performance kernels on **heterogeneous hardware platforms**(GPU/Ascend) and improve MindSpore training performance. + +The architecture and overall process are as follows: + +![graphkernel_akg_overview](./images/graphkernel_akg_overview.png) + +The overall framework of MindSpore AKG is shown in the figure above: + - IR Normalization + - The input of MindSpore AKG is the fusion subgraph optimized by MindSpore's graph-operator fusion module. The operators in the subgraph are expressed through various description methods such as TVM's Compute/IR Builder/Hybrid. Then the DSL is converted to [Halide](https://halide-lang.org/) IR (Halide, a common language used for developing high-performance image processing and array computation, which can be used as an intermediate representation to decouple algorithms and optimization) and IR normalization; + + - After initial simplification and optimization is completed, the Halide IR is transformed into the scheduling tree required by the Poly module; + + - Poly Module Scheduling Optimization + - Using the Pluto scheduling algorithm in polyhedral technology to achieve automatic loop fusion, automatic rearrangement and other transformations, automatically generating initial scheduling that satisfies parallelism and data locality for fusion operators; + + - To quickly adapt to different hardware backends, the optimization passes in the Poly module are divided into hardware-independent generic optimizations and hardware-related specific optimizations, which are stitched and combined according to hardware features at compilation time to achieve fast adaptation of heterogeneous hardware backends. Auto-slicing, auto-mapping, and auto-memory boosting passes will give different optimization methods according to the nature of different hardware architectures; + + - Backend Optimization + - To further improve operator performance, we developed corresponding optimization passes for different hardware backends, such as data alignment and instruction mapping in Ascend backend, vectorized access and insertion of synchronization instructions in GPU backend, and finally generate corresponding platform code. + +Summary: MindSpore compilation optimizes AI model code from various dimensions such as graph capture mode, IR optimization, graph-operator fusion, etc. Many features also face certain challenges in the trade-off between usability and performance. We also plan to further layer and decouple the entire process to avoid black-box operation and increase the threshold for developer understanding. \ No newline at end of file diff --git a/docs/mindspore/source_en/features/compile/graph_construction.md b/docs/mindspore/source_en/features/compile/graph_construction.md deleted file mode 100644 index bc30d9fe52..0000000000 --- a/docs/mindspore/source_en/features/compile/graph_construction.md +++ /dev/null @@ -1,181 +0,0 @@ -# Graph Construction (Compilation) - -[![View Source On Gitee](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source_en.svg)](https://gitee.com/mindspore/docs/blob/master/docs/mindspore/source_en/features/compile/graph_construction.md) - -MindSpore provides JIT (just-in-time) technology to optimize the performance. The JIT mode parses the code into an intermediate representation (IR) graph by means of AST tree parsing, Python bytecode parsing or code execution tracing, which serves as a unique representation of the code, and the compiler optimizes the code by optimizing the IR graph to improve the runtime performance. In contrast to the dynamic graph model, this JIT compilation model is called the static graph model. - -Based on JIT technology, MindSpore provides a dynamic-static combination approach to improve the operational efficiency of the user's network. The combination of dynamic and static, that is, in the overall run as a dynamic graph, specifies certain code blocks to run as a static graph. Code blocks that run as static graphs are compiled first and then executed, and global optimizations are performed during the compilation period to obtain performance gains during the execution period. Users can modify functions with the `@jit` decorator to specify that they execute according to the pattern of a static graph. For the documentation on the `@jit` decorator, refer to [jit API documentation](https://www.mindspore.cn/docs/en/master/api_python/mindspore/mindspore.jit.html#mindspore.jit). - -MindSpore provides three JIT compilation methods, namely, ast, bytecode and trace. The ast converts the functions that are identified by the users manually and need to be executed in accordance with the ast into a static graph through the AST tree parsing. The bytecode is through the Python bytecode parsing, in the dynamic graph as much as possible to build a static graph. The part that can not be converted to a static graph will be in accordance with the dynamic graph for the purpose of combining static and dynamic. The trace constructs a static graph by tracing the execution path of Python code and is currently an experimental feature. Subsequent introduction will explain in detail the difference among the three principles and their respective characteristics. - -## Ast - -In dynamic graph mode, the user can modify a function to execute in ast mode by using the `@jit(capture_mode=“ast”)` decorator. The syntax and data structures used inside the functions which decorated by ast mode need to strictly follow the [Static Graph Syntax Specification](https://www.mindspore.cn/tutorials/en/master/compile/static_graph.html). The ast approach compiles Python code via a source-to-source method, which first parses the Python source code of model definitions into an Abstract Syntax Tree (AST), then converts the AST into MindIR. For example, the following Python code: - -```python -@jit -def foo(x, y): - z = x + y - return z -``` - -The corresponding AST is as follows: - -![image](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/docs/mindspore/source_zh_cn/features/compile/images/ast.png) - -By parsing the above AST, we obtain the following MindIR: - -```text -%para1_x: -%para2_y: - -subgraph instance: foo -subgraph @foo() { - %0(CNode_17) = PrimFunc_Add(%para1_x, %para2_y) - : (, ) -> () - Return(%0) - : () -} -``` - -**ast Usage** - -The user can specify that the function is to be executed as a static graph via the `@jit` decorator, for example: - -```python -import numpy as np -import mindspore as ms -from mindspore import ops -from mindspore import jit -from mindspore import Tensor - -@jit -def tensor_cal(x, y, z): - return ops.matmul(x, y) + z - -x = Tensor(np.ones(shape=[2, 3]), ms.float32) -y = Tensor(np.ones(shape=[3, 4]), ms.float32) -z = Tensor(np.ones(shape=[2, 4]), ms.float32) -ret = tensor_cal(x, y, z) -print(ret) -``` - -```text -[[4. 4. 4. 4.] - [4. 4. 4. 4.]] -``` - -In the above use case, the tensor_cal function is modified by the @jit decorator, and the function follows the pattern of the static graph when it is called in order to capture the performance gains during the execution period of the function. - -**Advantages** - -- With the ast model, users have more programming autonomy and more precise performance optimization, allowing them to tune the performance of the network to the optimal level based on function characteristics and usage experience. - -**Limitations** - -- Functions modified by ast must be programmed with an internal syntax that strictly adheres to the static graph. - -**Recommendations for the Use of the ast Model** - -- In contrast to dynamic graph execution, a function modified by `@jit` consumes some time to compile a static graph the first time it is called. On subsequent calls to the function, if the original compilation result can be reused, the original compilation result will be used for execution. As a result, functions that are executed multiple times using @jit decorator usually gain more performance benefits. - -- The operational efficiency advantage of the static graph pattern is that it optimizes the compilation of @jit-modified functions globally. The more operations a function contains, the higher the upper limit of optimization. Therefore, functions modified by the `@jit` decorator should ideally be large chunks of code with a lot of operations, rather than many small, fragmented functions with only a few operations tagged with a separate jit tag. Otherwise, there may be no performance gain or even degradation. - -- The vast majority of calculations and optimizations for MindSpore static graphs are based on optimizations for Tensor calculations, so we recommend that the functions that are modified should be the kind of functions that are used to perform real data calculations, rather than simple scalar calculations or transformations of data structures. - -- Functions modified by `@jit` that have constants in their inputs will result in a recompile each time that the function input value changes. See [Constants and Variables Within JIT](https://www.mindspore.cn/tutorials/en/master/compile/static_graph.html#constants-and-variables-within-jit) for the concept of variable constants. Therefore, it is recommended that the modified function takes as input Tensor or data modified by Mutable. Avoid additional performance loss due to multiple compilations. - -## Bytecode - -In addition to ast, MindSpore provides another static acceleration mechanism, bytecode, which allows the user to modify a function to execute in bytecode mode via the `@jit(capture_mode=“bytecode”)` decorator. When bytecode recognizes that the syntax for entering a static graph is not supported, it will fall back to Python for execution instead of compiling directly and reporting errors. This feature combines performance and ease of use to reduce the occurrence of compilation errors. It is based on the analysis of Python bytecode, graph capture of Python execution flow, allowing subgraphs that can be run as static graphs to be run as static graphs, and allowing subgraphs that are not supported by Python syntax to be run as dynamic graphs, as well as linking the dynamic-static graphs by modifying and adjusting the bytecode, so as to achieve a mixed execution of dynamic and static. While meeting the premise of ease of use, to improve performance as much as possible. - -**bytecode Operating Principle** - -1. Capture the execution of Python functions based on Python VM_PyInterpreterState_SetEvalFrameFunc, which captures the execution of all Python functions in the execution area using context management. -2. Analyze the function bytecode in conjunction with the current runtime input parameters to construct a control flow graph (CFG) and a data flow graph (DFG). -3. Simulate in-stack and out-stack operations, trace bytecode by bytecode, and derive the output based on the stack inputs. Python 3.7 to Python 3.11 has a corresponding simulation implementation for each bytecode, noting that the type size of the outputs is derived, not the actual execution of the values, unless the constants are collapsed. -4. During the simulated execution of the bytecode, translate the derivation results and operations into MindIR, and finally, optimize the static graph by constant folding, UD analysis (removing useless input and output parameters), etc. -5. Before executing the equivalent static graph, compare the input parameters with the caretaker Guard conditions generated during the optimization process, and based on the runtime information, select the matching static graph for execution. -6. Dynamically manage the matching relationship between Guard and static graph buffer, recycle the unused static graph buffer, and optimize the static graph buffer through Symbolic Shape and Dynamic Shape. - -The compilation process of bytecode is illustrated in the following diagram: - -![image](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/docs/mindspore/source_zh_cn/features/compile/images/bytecode.png) - -**bytecode Usage** - -Setting the capture_mode parameter of jit to bytecode switches the mode of operation of the modifier function to bytecode, for example: - -```python -import numpy as np -import mindspore as ms -from mindspore import ops -from mindspore import jit -from mindspore import Tensor - -@jit(capture_mode="bytecode") -def tensor_cal(x, y, z): - return ops.matmul(x, y) + z - -x = Tensor(np.ones(shape=[2, 3]), ms.float32) -y = Tensor(np.ones(shape=[3, 4]), ms.float32) -z = Tensor(np.ones(shape=[2, 4]), ms.float32) -ret = tensor_cal(x, y, z) -print(ret) -``` - -```text -[[4. 4. 4. 4.] - [4. 4. 4. 4.]] -``` - -**Advantages** - -- Good user experience, no human intervention, user-written web code always runs properly, and code that can't be executed by static graphs will automatically run using dynamic graphs. -- bytecode can make more statements into the static graph by transforming the byte code. Users do not need to perceive or modify the code. - -**Limitations** - -- Users can't explicitly do performance acceleration for certain code, and for scenarios with more cracked graphs, the performance acceleration may not be obvious. - -## Trace - -MindSpore also offers another static acceleration mechanism called trace. Users can decorate a function with the `@jit(capture_mode=“trace”)` decorator to execute the function in trace mode. In this mode, the code first runs in pynative mode, during which the operators executed at runtime are recorded and captured into the computation graph. Subsequent executions of the decorated code will directly execute the computation graph constructed during the first execution. This mechanism does not parse syntax but only captures the operators called during runtime, thus avoiding syntax-related errors. It captures the operators invoked during the execution of the pynative mode, captures the Python execution flow into a graph, and compiles the captured operators into the computation graph. Operations without corresponding operators will have their return values recorded as constants in the computation graph. The generated computation graph runs in the manner of static graph execution. - -**trace Usage** - -Setting the capture_mode parameter of jit to trace switches the mode of operation of the modifier function to trace, for example: - -```python -import numpy as np -import mindspore as ms -from mindspore import ops -from mindspore import jit -from mindspore import Tensor - -@jit(capture_mode="trace") -def tensor_cal(x, y, z): - return ops.matmul(x, y) + z - -x = Tensor(np.ones(shape=[2, 3]), ms.float32) -y = Tensor(np.ones(shape=[3, 4]), ms.float32) -z = Tensor(np.ones(shape=[2, 4]), ms.float32) -ret = tensor_cal(x, y, z) -print(ret) -``` - -```text -[[4. 4. 4. 4.] - [4. 4. 4. 4.]] -``` - -**Advantages of trace** - -- The graph construction capability is robust; as long as the code has corresponding operators, they can be captured into the graph without the need for additional adaptation. There will be no syntax-related errors when building the static graph. -- Good user experience, no human intervention, user-written web code always runs properly. - -**Limitations of trace** - -- It is unable to detect the control flow within the code, and correctness cannot be ensured in scenarios where different branches of the control flow are entered during multiple executions. -- Operations in the code that are not defined as operators, such as calls to third-party libraries, are fixed as constants in the computation graph, and correctness cannot be guaranteed across multiple runs. - diff --git a/docs/mindspore/source_en/features/compile/graph_optimization.md b/docs/mindspore/source_en/features/compile/graph_optimization.md deleted file mode 100644 index 00bb22bb19..0000000000 --- a/docs/mindspore/source_en/features/compile/graph_optimization.md +++ /dev/null @@ -1,318 +0,0 @@ -# Graph Optimization (Compilation) - -[![View Source On Gitee](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source_en.svg)](https://gitee.com/mindspore/docs/blob/master/docs/mindspore/source_en/features/compile/graph_optimization.md) - -Similar to traditional compilers, MindSpore also performs compilation optimization after graph construction. The main purpose of compilation optimization is to analyze and transform MindSpore's intermediate representation MindIR by static analysis techniques to achieve goals such as reducing the size of the target code, improving execution efficiency, lowering runtime resource consumption, or enhancing other performance metrics. Compilation optimization is a crucial part of the graph compilation system and plays an extremely important role in improving the performance and resource utilization of the entire neural network model. Compared with the original code that has not been optimized, compilation optimization can bring several times or even tens of times performance improvement. - -This section mainly introduces front-end compilation optimization techniques that are independent of specific hardware. Hardware-specific back-end compilation optimization techniques are not within the scope of this discussion. - -## Principles of Front-End Compilation Optimization Techniques - -Similar to traditional compilation optimization techniques, compilation optimization in MindSpore is also carried out through a series of Passes. Each Pass takes the MindIR produced by the previous Pass as input and generates a new MindIR representation as output after optimization. A large Pass can include multiple smaller Passes, each of which is only responsible for a single point of compilation optimization, such as arithmetic simplify, inline, redundancy elimination and etc. The optimization results produced by one Pass may create optimization opportunities for other Passes, so these Passes can be run in a loop until the MindIR no longer changes. - -The selection of which Passes to run and how to arrange the execution order of these Passes has a very important impact on the final compilation result. Depending on the actual situation, the optimization actions to be performed can be adjusted by setting compilation optimization strategies (such as optimization levels, number of iterations, etc.). - -## Common Front-End Compilation Optimization Techniques - -There are many front-end compilation optimization techniques, such as arithmetic simplify, inline, and redundancy elimination. This section will introduce some representative compilation optimization techniques. - -### Arithmetic Simplify - -In traditional compilers, arithmetic simplify is a compiler optimization technique aimed at simplifying algebraic expressions in source code, eliminating redundant calculations, improving program execution efficiency, and reducing memory usage. - -For example, in the following code snippet: - -```cpp -int a = x * 1; -int b = x + 0; -int c = x * 0 + y * 1; -``` - -Traditional compilers perform equivalent substitution on recognized expressions based on algebraic rules and identities. Common algebraic rules include laws of union, commutative, and distributive, and compilers will try to replace expressions with simpler forms as much as possible. By analyzing AST or SSA analysis is used for optimization, identifying and simplifying code as follows: - -```cpp -a = x; -b = x; -c = y; -``` - -In the MindSpore compiler, the principle of arithmetic simplify is different from traditional compilers. It processes computational graphs rather than traditional control flow graphs. By adjusting the execution order of operators in the computational graph or deleting unnecessary operators, it maintains the simplicity of the graph and improves computational efficiency. - -For example, in the following Python code snippet: - -```python -import numpy as np -from mindspore.common import Tensor, jit - -@jit -def func(x): - return x + 0 - -m = Tensor(np.array([[1, 2, 3], [4, 5, 6]]).astype(np.int32)) -out = func(m) -``` - -The MindSpore graph compiler converts Python programs into computational graphs, which consist of multiple subgraphs. The algebraic operations in the source code are converted into operator calls within the subgraph, and it can be seen that the PrimFunc_Add operator is called once. - -```text -%para1_x: - -subgraph @1_func_14() { - %0(CNode_7) = PrimFunc_Add(%para1_x, Tensor(shape=[], dtype=Int32, value=0)) - : (, ) -> () - - Return(%0) - : () -} -``` - -By arithmetic simplify, the PrimFunc_Add operator can be directly removed to simplify the computational graph structure, reducing `x + 0` to `x`. - -```text -%para1_x: - -subgraph @1_func_14() { - Return(%para1_x) - : () -} -``` - -Arithmetic simplify can involve more modifications to the structure of computational graphs, and it is often combined with other compiler optimization techniques such as constant folding and constant propagation to improve program performance. - -### Inline - -In traditional compilers, inline is an optimization technique that replaces function calls with the actual code of the called function, improving program performance. For example, consider a C++ `add` function that sums two numbers: - -```cpp -int add(int a, int b) { - return a + b; -} - -int main() { - int x = add(3, 5); - int y = add(x, 10); - return y; -} -``` - -The compiler uses inline to directly insert the function body at the call site. This eliminates function call overhead and enables follow-up optimizations (e.g., replacing `3 + 5` with its result at compile time). **Replacing calls with code** is the core idea of inline. - -```cpp -int main() { - int x = 3 + 5; // Replace the first call. - int y = x + 10; // Replace the second call. - return y; -} -``` - -In AI frameworks' computational graph compilers, inline serves a similar purpose but operates on "subgraphs" instead of functions. For example, consider a Python program: - -```python -from mindspore import Tensor, jit, ops - -def f2(x: Tensor, y: Tensor): - return x * 0.5 + y - -@jit -def f1(a: Tensor, b: Tensor, c: Tensor): - x = f2(a, b) - y = f2(a, c) - return x + y - -# Create three Tensors with random values, each having a shape of (2, 4). -a = ops.randn(2, 4) -b = ops.randn(2, 4) -c = ops.randn(2, 4) -out = f1(a, b, c) -``` - -First, MindSpore's graph compiler converts the Python program into a computational graph. The function calls in the Python program are converted into calls between calculation graphs, and the original calculation graph is similar to the following. The main graph `f1` calls the subgraph `f2` twice. - -```text -# Params: -%para1_a: -%para2_b: -%para3_c: - -subgraph @f2(%para1_x, %para2_y) { - %0 = PrimFunc_Mul(%para1_x, Float32(0.5)) - - %1 = PrimFunc_Add(%0, %para2_y) - - Return(%1) -} - -subgraph @f1() { - %0(x) = call @f2(%para1_a, %para2_b) # Call subgraph f2 - - %1(y) = call @f2(%para1_a, %para3_c) # Call subgraph f2 - - %2 = PrimFunc_Add(%0, %1) - - Return(%2) -} -``` - -With inlining, the subgraph `f2` can be expanded and merged into the main graph `f1`. - -```text -subgraph @f1() { - # First-time subgraph inlining - %0 = PrimFunc_Mul(%para1_a, Float32(0.5)) # Repeated computation - %1 = PrimFunc_Add(%0, %para2_b) - - # Second-time subgraph inlining - %2 = PrimFunc_Mul(%para1_a, Float32(0.5)) # Repeated computation - %3 = PrimFunc_Add(%2, %para3_c) - - %4 = PrimFunc_Add(%1, %3) - - Return(%4) -} -``` - -Before inlining, the compiler might not detect repeated operations in the two calls to subgraph `f2` (as subgraphs are often treated as black boxes). After inlining, the compiler clearly sees `x * 0.5` calculated twice, enabling optimizations like **CSE** (Common Subexpression Elimination) to reduce redundant computations. - -```text -subgraph @f1() { - %0 = PrimFunc_Mul(%para1_a, Float32(0.5)) # CSE merges redundant computations - - %1 = PrimFunc_Add(%0, %para2_b) - - %2 = PrimFunc_Add(%0, %para3_c) # Directly reuse %0 - - %3 = PrimFunc_Add(%1, %2) - - Return(%3) -} -``` - -With inlining, compilers better identify cross-subgraph optimization opportunities. In addition to CSE, it enables operator fusion, memory management optimizations, and many other optimizations. Thus, inline is a critical optimization mechanism in computational graph compilers and a foundation for many cross-subgraph optimizations. - -### Redundancy Elimination - -In traditional compilers, redundancy elimination encompasses various compiler optimization techniques aimed at identifying and removing redundant parts of the code during compilation. This process is designed to reduce unnecessary computations and improve the execution efficiency of programs. - -Redundant code may be intentionally written by developers for readability purposes or may simply be an unintentional result of the coding process. Additionally, intermediate results generated by other optimization techniques during the compilation process (such as arithmetic simplify, inline and common subexpression elimination) may also create opportunities for redundancy elimination. - -There are many techniques for redundancy elimination. This section selects and introduces some of the common ones, including dead code elimination and unreachable code elimination. - -1. **Dead code elimination** - - Removing code whose results are not used. For example, in the following C++ code, the variable `c` is not used by any other code. Compilers can use data flow analysis techniques from the field of static analysis to eliminate the computation of code: `int c = x * y`. - - ```cpp - int func(x, y) { - int a = x + y; - int b = x - y; - int c = x * y; // Dead code - int d = a / b; - return d; - } - ``` - -2. **Unreachable code elimination** - - Removing code that is not included in any valid control flow path. For example, in the following C++ code, compilers can use control flow analysis techniques from the field of static analysis to analyze the control flow graph. They can identify that the expression `1 < 0` is always false, and thus the code within this control flow path will never be executed during actual runtime. Therefore, the code in this branch can be eliminated. - - ```cpp - int func(x, y) { - int a = x + y; - - int b; - if 1 < 0 { // Unreachable branch - b = x + y; - } else { - b = x - y; - } - - int d = a / b; - return d; - } - ``` - -In MindSpore's graph mode, the purpose and techniques of redundancy elimination are similar to those in traditional compilers. However, unlike traditional compilers, these redundancy optimization techniques are performed on MindIR. Similarly, common redundancy elimination techniques in MindSpore include: - -1. **Dead code elimination** - - For example, consider the following Python code with redundant computations: - - ```python - import mindspore as ms - from mindspore.common import Tensor, jit - - @jit - def func(x, y): - a = x + y - b = x - y - c = x * y # Dead code - d = a / b - return d - - x = Tensor(20, ms.float32) - y = Tensor(10, ms.float32) - out = func(x, y) - ``` - - The MindSpore graph compiler will convert the Python code decorated with `@jit` into the MindIR representation through static analysis and eliminate the redundant computation `c = x * y`. The resulting MindIR is as follows: - - ```text - # Params: - %para1_x: - %para2_y: - - subgraph @func_1() { - %0(a) = PrimFunc_Add(%para1_x, %para2_y) - : (, ) -> () - %1(b) = PrimFunc_Sub(%para1_x, %para2_y) - : (, ) -> () - %2(d) = PrimFunc_Div(%0, %1) - : (, ) -> () - Return(%2) - : () - } - ``` - -2. **Unreachable code elimination** - - For example, consider the following Python code with an unreachable path: - - ```python - import mindspore as ms - from mindspore.common import Tensor, jit - - @jit - def func(x, y): - a = x + y - if 1 < 0: # Unreachable branch - b = x + y - else: - b = x - y - d = a / b - return d - - x = Tensor(20, ms.float32) - y = Tensor(10, ms.float32) - out = func(x, y) - ``` - - The MindSpore graph compiler will convert the Python code decorated with `@jit` into the MindIR representation through static analysis and eliminate the redundant control flow branch `1 < 0`. The resulting MindIR is as follows: - - ```text - # Params: - %para1_x: - %para2_y: - - subgraph @func_1() { - %0(a) = PrimFunc_Add(%para1_x, %para2_y) - : (, ) -> () - %1(b) = PrimFunc_Sub(%para1_x, %para2_y) - : (, ) -> () - %2(d) = PrimFunc_Div(%0, %1) - : (, ) -> () - Return(%2) cnode_attrs: {checkpoint: Bool(1)} - : () - } - ``` - -Redundancy elimination plays a crucial role in compiler optimization. Without changing the original semantics of the program, it can significantly improve execution efficiency by reducing unnecessary runtime computations and saving computing resources. Redundancy elimination is often combined with other compiler optimization techniques to create more opportunities for eliminating redundant code. diff --git a/docs/mindspore/source_en/features/compile/images/graphkernel.png b/docs/mindspore/source_en/features/compile/images/graphkernel.png new file mode 100644 index 0000000000000000000000000000000000000000..06a5af7b00a222044a5a83bbde72a263fd6d3dd9 GIT binary patch literal 23883 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 literal 0 HcmV?d00001 diff --git a/docs/mindspore/source_en/features/compile/images/graphkernel_akg_overview.png b/docs/mindspore/source_en/features/compile/images/graphkernel_akg_overview.png new file mode 100644 index 0000000000000000000000000000000000000000..18089ee5c51d88733d58ef22b9e394753116306b GIT binary patch literal 217579 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

pD6Q=KYx5ym@yX} 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 z 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 Nv6ZK502B$T`1$xyQ` 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 z kernel2-> kernel4-> kernel5-> kernel3-> kernel6. Memory peaks at 5G (kernel3 can release kernel1 and kernel2 after execution, and then reuse them when it's kernel6's turn to execute, so kernel6 doesn't need to request extra memory). -- **Execution order obtained by DFS**: kernel1-> kernel2-> kernel3-> kernel4-> kernel5-> kernel6. Memory peaks at 4G (kernel3 can release kernel1 and kernel2 after execution, and then reuse them when it's kernel4 and kernel5's turn to execute, so kernel4 and kernel5 don't need to request extra memory). - -Execution order scheduling is a complex problem of solving optimal operator concurrency under certain memory constraints, which not only requires identifying and exploiting concurrency opportunities in the computational graph to improve computational efficiency, but also must consider multiple constraints at the same time to ensure the stability and efficiency of the system. - -- First, the optimization module needs to address the complexity of solving for optimal operator concurrency. Due to the large number of operators in the computational graph and their interdependencies, finding an execution order that maximizes concurrency while maintaining the logical correctness of the computational graph is a challenging task. -- Second, memory constraints are a critical factor that cannot be ignored in execution order optimization. Increasing concurrency, while improving computational efficiency, tends to significantly increase peak memory requirements, which may lead to Overflow of Memory (OOM) errors, especially in resource-constrained environments. Therefore, the optimization module must weigh the relationship between concurrency and memory usage to ensure that concurrency is increased without exceeding the memory capacity of the system. -- MindSpore's execution order adjustment module combines rule-based and heuristic-based strategies to provide both bfs/dfs execution order orchestration algorithms [mindspore.jit(option={“exec_order”: “bfs/dfs”})](https://www.mindspore.cn/docs/en/master/api_python/mindspore/mindspore.jit.html#mindspore.jit) to achieve fine-grained adjustment of the execution order of the computation graph, so as to effectively deal with multiple challenges such as memory constraints and system stability while ensuring computational efficiency. - -## Introduction to the O1 Model - -O1 is mainly targeted at implementing general-purpose, generalizable AI compilation optimizations on top of O0 to support better execution performance requirements for most general-purpose training and inference scenarios. - -In the current phase, O1 mainly supports graph-kernel fusion optimization. The main idea is to automatically identify neighboring fusable nodes in the computational graph during the static graph compilation phase, and then fuse them into executable operators with larger granularity. Through graph-kernel fusion, optimization effects such as increasing the computational locality of operators and reducing the overall global memory access bandwidth overhead are achieved. As verified by real-world tests on more than 15 networks, O1 is able to achieve an average of 15% performance acceleration compared to O0. Especially for access-intensive networks, the optimization effect of O1 is more significant. - -### Graph-Kernel Fusion - -Mainstream AI computing frameworks such as MindSpore provides operators to users that is usually defined in terms of understandable and easy use for user. Each operator carries a different amount of computation and varies in computational complexity. However, from the hardware execution point of view, this natural, user perspective-based division of operator computation volume is not efficient and does not fully utilize the computational power of hardware resources, which is mainly reflected in the following aspects: - -1. Computationally overloaded and overly complex operators, which usually makes it difficult to generate well-cut high-performance operator, thereby reducing equipment utilization. -2. Operators that are too small in computation may also cause latency in computation and thus reduce equipment utilization, as the computation cannot effectively hide the data moving overhead. -3. Hardware Devices are usually multi-core, many-core architectures. When the operator shape is small or other reasons cause insufficient computational parallelism, it may cause some cores to be idle, thus reducing the device utilization. In particular, chips based on Domain Specific Architecture (DSA for short) are more sensitive to these factors. It has been a big challenge to maximize the performance of hardware operator while making the operator easy to use. - -In terms of AI framework design, the current industry mainstream adopts a separate layer implementation approach of graph and operator layers. The graph layer is responsible for fusing or regrouping the computational graph, and the operator layer is responsible for compiling the fused or regrouped operators into high-performance executable operators. The graph layer is usually processed and optimized by using Tensor-based High-Level IR, while the operator layer is analyzed and optimized by using computational instruction-based Low-Level IR. This artificial separate-layer process significantly increases the difficulty of performing collaborative optimization in both graph and computational layers. - -MindSpore has adopted the technique of graph-kernel fusion to better solve this problem in the past few years. Typical networks in different categories such as NLP and recommendation show significant gains in training speed after enabling graph-kernel fusion. One of the main reasons is the presence of a large number of small operator combinations in these networks, which have more opportunities for fusion optimization. - -#### Graph-Kernel Fusion Architecture and Overall Process - -The overall architecture of graph-kernel fusion is shown in the figure below. The main idea in the graph layer is to turn on the composite operator, then perform cross-boundary aggregation and optimization, and finally perform Kernel operator splitting. The main steps include: - -1. Composite Expansion: Expand the composite operator into the basic operator and form the Composite subgraph to facilitate subsequent cross-boundary optimization and operator splitting. -2. Cross-OP Aggregation: Aggregate adjacent elementary operators or Composite subgraphs to form larger aggregated subgraphs for subsequent cross-boundary optimization and operator splitting. -3. High-Level Optimization: Based on the aggregated subgraphs obtained in the above two steps, we can perform a large number of cross-boundary optimizations, such as algebraic simplification, common subexpression extraction (CSE). -4. Kernel Partition: Based on the computational features and the performance of the fusion operator, the operator splitting is performed on the aggregated computational subgraph. - -The optimized computational graph is passed to MindSpore AKG as a subgraph for further back-end optimization and target code generation. - -![graphkernel](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/docs/mindspore/source_zh_cn/features/images/graphkernel.png) - -By following these steps, we can obtain two aspects of performance gains: - -1. Cross-boundary performance optimization gains between different operators. -2. The optimal granularity of the fusion operator is obtained by reorganizing and splitting the entire computational graph. - -#### Fusion Operator Acceleration Optimization (MindSpore AKG) - -As mentioned earlier, in scenarios such as HPC and deep neural network training, graph-kernel fusion optimization can bring exponential performance improvements. However, with the increasing capability of graph-kernel fusion, the development of fusion operator becomes a bottleneck point to continue to improve the graph-kernel fusion capability. - -The automatic generation technology of fusion operators can solve the problem of high programming threshold for developing fusion operators based on DSA, allowing programmers to focus on the implementation logic of operators during operator development without focusing on back-end optimization, which greatly improves their development efficiency. Especially for scenarios with complex back-end hardware architectures and the presence of complex operators and fusion operators, automatic operator generation techniques are more critical. - -Therefore, **MindSpore AKG accelerates optimization and automatic generation of fusion operator based on Polyhedral Compilation Technology (Polyhedral Model)**, can help fused operators optimized by MindSpore graph-kernel fusion module to automatically generate high-performance kernel on **heterogeneous hardware platforms** (GPU/Ascend) and improve MindSpore training performance. - -Architecture and Overall Process are as follows: - -The overall framework of MindSpore AKG is shown in the figure above: - -- IR Normalization - - The input of MindSpore AKG is the fused subgraph optimized by MindSpore graph-kernel fusion module, and the operator in the subgraph is expressed by various descriptions such as TVM's Compute/IR Builder/Hybrid. The DSL is then converted to Halide IR ([Halide](https://halide-lang.org/), a common language used to develop high-performance image processing and Array computation, which can be used as an intermediate expression for decoupling algorithms and optimization) and IR normalization. - - After the initial simplification and optimization is completed, the Halide IR is transformed into the scheduling tree required by the Poly module. -- Poly module scheduling optimization - - Using the Pluto scheduling algorithm in Polyhedral technology to achieve automatic fusion of loops, automatic rearrangement and other transformations to automatically generate an initial schedule that satisfies parallelism and data locality for the fusion operator. - - To quickly adapt to different hardware backends, the optimization pass in the Poly module is divided into hardware-independent generic optimizations and hardware-related specific optimizations, which are stitched and combined according to hardware features at compilation time, to achieve fast adaptation of heterogeneous hardware backends. The pass such as Auto-slicing, auto-mapping and auto-memory boosting will give different optimizations depending on the nature of the hardware architecture. -- Backends optimization - - In order to further improve the performance of the operator, we developed corresponding optimization passes for different hardware backends, such as data alignment and instruction mapping in Ascend backend, vectorized access and insertion of synchronization instructions in GPU backend, and finally generated the corresponding platform code. - -### Other Graph Optimization Techniques - -In addition to graph-kernel fusion, O1 may be gradually extended to add some other graph optimization techniques in subsequent releases. For example: - -1. KernelPacket: automatic fusion and optimization of shape computations in dynamic shape scenarios; -2. Communicative-kernel fusion: fusion of communication operators with computational operators. diff --git a/docs/mindspore/source_en/features/overview.md b/docs/mindspore/source_en/features/overview.md index 2899bbfb4b..c1385397f4 100644 --- a/docs/mindspore/source_en/features/overview.md +++ b/docs/mindspore/source_en/features/overview.md @@ -31,19 +31,21 @@ The overall architecture of MindSpore is as follows: MindSpore is a full-scenario deep learning framework designed to achieve three major goals: easy development, efficient execution, and unified deployment across all scenarios. Easy development is reflected in API friendliness and low debugging difficulty; efficient execution includes computational efficiency, data preprocessing efficiency, and distributed training efficiency; full-scenario means the framework simultaneously supports cloud, edge, and device-side scenarios. -### Fusion of Functional and Object-Oriented Programming Paradigms +### Programming Paradigms and Experience (pynative + graph mode) + +#### Fusion of Functional and Object-Oriented Programming MindSpore provides both object-oriented and function-oriented programming paradigms, both of which can be used to construct network algorithms and training processes. Developers can derive from the nn.Cell class to define AI networks or layers with required functionality, and assemble various defined layers through nested object calls to complete the definition of the entire AI network. -At the same time, developers can also define a pure Python function that can be source-to-source compiled by MindSpore, and accelerate its execution through functions or decorators provided by MindSpore. Under the requirements of MindSpore's static syntax, pure Python functions can support nested subfunctions, control logic, and even recursive function expressions. Therefore, based on this programming paradigm, developers can flexibly enable certain functional features, making it easier to express business logic. +At the same time, developers can also define a pure Python function that can be source-to-source compiled by MindSpore, and accelerate its execution through functions or decorators provided by MindSpore. Under the requirements of MindSpore graph mode syntax, pure Python functions can support nested subfunctions, control logic, and even recursive function expressions. Therefore, based on this programming paradigm, developers can flexibly enable certain functional features, making it easier to express business logic. MindSpore implements functional differential programming, which performs differentiation based on the call chain according to the calling relationship for function objects that can be differentiated. This automatic differentiation strategy better aligns with mathematical semantics and has an intuitive correspondence with composite functions in basic algebra. As long as the derivative formulas of basic functions are known, the derivative formula of a composite function composed of any basic functions can be derived. At the same time, based on the functional programming paradigm, MindSpore provides rich higher-order functions such as vmap, shard, and other built-in higher-order functions. Like the differential function grad, these allow developers to conveniently construct a function or object as a parameter for higher-order functions. Higher-order functions, after internal compilation optimization, generate optimized versions of developers' functions, implementing features such as vectorization transformation and distributed parallel partitioning. -### Unified Programming Experience for Dynamic and Static Graphs +#### Unified Programming Experience for Pynative and Graph Mode Traditional AI frameworks mainly have two programming execution forms: static graph mode and dynamic eager mode. @@ -67,16 +69,18 @@ MindSpore introduced Tensor Redistribution (TR) technology in parallel strategy At the same time, MindSpore also provides various parallel strategies such as pipeline parallelism, optimizer parallelism, and recomputation for developers to use. -### High-Performance Hardware Utilization +### Compilation Based on compilation technology, MindSpore provides rich hardware-independent optimizations such as IR fusion, algebraic simplification, constant folding, and common subexpression elimination. At the same time, it also provides various hardware optimization capabilities for different hardware such as NPU and GPU, thereby better leveraging the large-scale computational acceleration capabilities of hardware. -#### [Graph-Algorithm Fusion](https://www.mindspore.cn/docs/en/master/features/compile/multi_level_compilation.html#graph-kernel-fusion) +#### [Multi-Level Compilation Architecture](https://www.mindspore.cn/docs/en/master/features/compile/compilation_guide.html) Mainstream AI computing frameworks like MindSpore typically define operators from the perspective of developer understanding and ease of use. Each operator carries varying amounts of computation and computational complexity. However, from a hardware execution perspective, this natural operator computational division based on the developer's perspective is not efficient and cannot fully utilize hardware computational capabilities. This is mainly reflected in: 1. Operators with excessive computational volume or complexity are usually difficult to generate well-partitioned high-performance operators, thereby reducing device utilization; + 2. Operators with too little computational volume may cause computational waiting latency due to the inability to effectively hide data movement overhead, thereby reducing device utilization; + 3. Hardware devices are typically multi-core or many-core structures, and when operator shapes are small or other reasons cause insufficient computational parallelism, some cores may remain idle, thereby reducing device utilization. This is especially sensitive for chips based on Domain Specific Architecture (DSA). How to maximize hardware computational performance while ensuring operators are easy to use has always been a significant challenge. In terms of AI framework design, the industry mainstream currently adopts a layered implementation method with graph layer and operator layer. The graph layer is responsible for fusing or reorganizing the computational graph, while the operator layer is responsible for compiling the fused or reorganized operators into high-performance executable operators. The graph layer typically uses High-Level IR processing and optimization based on Tensor, while the operator layer uses Low-Level IR analysis and optimization based on computational instructions. This artificial layering significantly increases the difficulty of coordinated optimization between the graph and operator layers. @@ -101,6 +105,6 @@ MindSpore is an AI framework that integrates training and inference, supporting According to actual execution environments and business requirements, MindSpore provides multiple specification versions, supporting deployment on cloud, servers, mobile and other embedded devices, and ultra-lightweight devices such as earphones. -### [Third-Party Hardware Integration](https://www.mindspore.cn/docs/en/master/features/runtime/pluggable_device.html) +### Third-Party Hardware Integration Based on the unified MindIR, MindSpore has built an open AI architecture that supports third-party chip plugins, standardization, and low-cost rapid integration, which can connect to GPU series chips as well as various DSA chips. MindSpore provides two chip integration methods: Kernel mode and Graph mode, allowing chip manufacturers to choose the integration method according to their own characteristics. diff --git a/docs/mindspore/source_zh_cn/features/compile/graph_optimization.md b/docs/mindspore/source_zh_cn/features/compile/compilation_guide_zh.md similarity index 33% rename from docs/mindspore/source_zh_cn/features/compile/graph_optimization.md rename to docs/mindspore/source_zh_cn/features/compile/compilation_guide_zh.md index e3d8f79424..fa0411c9fd 100644 --- a/docs/mindspore/source_zh_cn/features/compile/graph_optimization.md +++ b/docs/mindspore/source_zh_cn/features/compile/compilation_guide_zh.md @@ -1,22 +1,83 @@ -# 图优化(编译) +# mindspore.jit 多级编译优化 -[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/mindspore/source_zh_cn/features/compile/graph_optimization.md) +[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/mindspore/source_zh_cn/features/compile/compilation_guide_zh.md) -与传统编译器类似,MindSpore 在进行完构图之后,也会进行编译优化。编译优化的主要目的是通过静态分析技术对 MindSpore 的中间表示 MindIR 进行分析和转换,以达成减小目标代码大小、提升代码执行效率、降低运行时资源开销或者提升其它性能指标的目的。编译优化是图编译系统中的重要一环,对提升整个神经网络模型的性能和资源利用率有着极其重要的意义,相较于未经过编译优化的原始代码,编译优化可能带来数倍甚至数十倍的性能提升。 -本节主要介绍独立于特定硬件的前端编译优化技术,特定于硬件的后端编译优化技术不在本节的讨论范围之内。 +## MindSpore编译架构 + +MindSpore利用jit(just-in-time)来进行性能优化。jit模式会通过AST树解析、Python字节码解析或追踪代码执行的方式,将python代码转换为中间表示图(IR,Intermediate Representation)。我们给它命名MindIR。编译器通过对该IR图的优化,来达到对代码的优化,提高运行性能。与动态图模式相对应,这种JIT的编译模式被称为graph mode。 -## 前端编译优化技术原理 +开发者写的python代码默认以动态图模式运行,可以通过`@mindspore.jit`装饰器修饰函数,来指定其按照graph mode执行。有关`@mindspore.jit`装饰器的相关文档请见[jit 文档](https://www.mindspore.cn/docs/zh-CN/master/api_python/mindspore/mindspore.jit.html#mindspore.jit)。 -与传统编译优化技术类似,MindSpore 中的编译优化也是通过一个个 Pass 来完成的。将每个 Pass 的上一个 Pass 所产生的 MindIR 作为输入,经过本 Pass 优化之后,产生新的 MindIR 表示作为输出。一个大的 Pass 可以包含多个小的 Pass,每个小的 Pass 只负责单点的编译优化,如:代数化简、函数内联(inline)、冗余消除等。一个 Pass 产生的优化结果,可能会为其它的 Pass 带来优化机会,故可以循环运行这些 Pass,直到产生的 MindIR 不再发生变化为止。 +graph mode大致分为3个阶段: + - 图捕获(构图): python代码 -> MindIR。 + - 图优化(前端): 对MindIR进行硬件无关优化,代数化简、函数inline(内联)、冗余消除等。 + - 图优化(后端): 对MindIR进行硬件相关优化,LazyInline,算子选择,图算融合等。 + +## 图捕获(构图) + +MindSpore提供三种捕获方式,如下 + - AST: 通过AST树解析的方式将执行的函数转换成IR图 + - bytecode(实验性): 对Python字节码的解析,尽可能的构建IR图,无法转换为IR图的部分则会按照动态图进行执行 + - trace(实验性): 通过追踪Python代码执行的轨迹来构建IR图 + +这三种模式在mindspore.jit中使用capture_mode来选择,以ast举例: 开发者可用`@mindspore.jit(capture_mode="ast")`装饰器修饰函,用ast方式修饰的函数,其语法有一定限制,我们提供两种模式供开发者选择。 +- strict模式:此模式目标是构成一张图,开发者的python代码如果无法构图,选择此模式运行程序时会报错,需要开发者进行代码修改,变为可构图的语法,适合追求性能的开发者。 +- lax模式:此模式目标是尽可能的让开发者程序可运行,思路是针对无法在strict模式构图的代码进行python fallback,即返回python层运行。 + +graph mode模式约束请参考[语法约束](https://www.mindspore.cn/tutorials/zh-CN/master/compile/static_graph.html)。ast如何将python代码解析并构图,举例如下: + +```python +@mindspore.jit +def foo(x, y): + z = x + y + return z +``` + +它对应的抽象语法树如下: + +![抽象语法树](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/docs/mindspore/source_zh_cn/features/compile/images/ast.png) + +通过解析上面的抽象语法树,我们得到下面的IR: + +```text +%para1_x: +%para2_y: + +subgraph instance: foo +subgraph @foo() { + %0(CNode_17) = PrimFunc_Add(%para1_x, %para2_y) + : (, ) -> () + Return(%0) + : () +} +``` + +**ast的优点**: + +- 使用ast模式,用户的编程自主性更强,性能优化更精准,可以根据函数特征以及使用经验将网络的性能调至最优。 + +**ast的限制**: + +- ast修饰的函数,其内部的语法必须严格遵守静态图语法来进行编程。 + +**ast模式的使用建议**: + +- 相比于动态图执行,被`@mindspore.jit`修饰的函数,在第一次调用时需要先消耗一定的时间进行编译。在该函数的后续调用时,若原有的编译结果可以复用,则会直接使用原有的编译结果进行执行。因此,使用@mindspore.jit装饰器修饰会多次执行的函数通常会获得更多的性能收益。 -编译优化过程中,选择运行哪些 Pass,如何安排这些 Pass 的执行顺序对生成的最终的编译结果有着非常重要的影响。可以按照实际情况,通过设定编译优化策略(如优化级别、次数等)来对即将执行的优化动作进行调整。 +- graph mode的运行效率优势体现在其会将被@mindspore.jit修饰函数进行全局上的编译优化,函数内含有的操作越多,优化的空间越大。因此`@mindspore.jit`装饰器修饰的函数最好是内含操作很多的大代码块,而不应将很多细碎的、仅含有少量操作的函数分别打上jit标签。否则,则可能会导致性能没有收益甚至劣化。 -## 常见前端编译优化技术 +- 绝大部分计算以及优化都是基于对Tensor计算的优化,建议被修饰的函数应该是用来进行真正的数据计算的函数,而不是一些简单的标量计算或者数据结构的变换。 -前端编译优化技术有很多,如:代数化简、函数inline(内联)、冗余消除等。本节将介绍部分具有代表性的编译优化技术。 +- 被`@mindspore.jit`修饰的函数,若其输入存在常量,那么该函数每次输入值的变化都会导致重新编译,关于变量常量的概念请见[即时编译下的常量与变量](https://www.mindspore.cn/tutorials/zh-CN/master/compile/static_graph)。因此,建议被修饰的函数以Tensor或者被Mutable修饰的数据作为输入。避免因多次编译导致的额外性能损耗。 -### 代数化简 +## 图优化(前端) + +与传统编译优化技术类似,MindSpore 中的编译优化也是通过一个个 Pass 来完成的。将每个 Pass 的上一个 Pass 所产生的 MindIR 作为输入,经过本 Pass 优化之后,产生新的 MindIR 表示作为输出。一个大的 Pass 可以包含多个小的 Pass,每个小的 Pass 只负责单点的编译优化,如:代数化简、函数内联(inline)、冗余消除等。一个 Pass 产生的优化结果,可能会为其它的 Pass 带来优化机会,故可以循环运行这些 Pass,直到产生的 MindIR 不再发生变化为止。 + +前端编译优化技术有很多,如: 代数化简、函数inline(内联)、冗余消除等。这里仅介绍具有代表性的编译优化技术。 + +### 1 代数化简 在传统编译器中,代数化简是一种编译器优化技术,旨在简化源代码中的代数表达式,消除多余计算,提高程序执行效率、减少内存占用等。 @@ -42,13 +103,13 @@ c = y; ```python import numpy as np -from mindspore.common import Tensor, jit +import mindspore -@jit +@mindspore.jit def func(x): return x + 0 -m = Tensor(np.array([[1, 2, 3], [4, 5, 6]]).astype(np.int32)) +m = mindspore.tensor(np.array([[1, 2, 3], [4, 5, 6]]).astype(np.int32)) out = func(m) ``` @@ -79,7 +140,7 @@ subgraph @1_func_14() { 代数化简能更多地涉及对计算图结构的修改,它通常还与其他编译器优化技术(如常量折叠、常量传播等)结合使用,共同提高程序性能。 -### 函数inline +### 2 函数inline 在传统编译器中,inline(内联)是一种优化技术,可以把被调用函数的代码直接替换到调用该函数的位置,提高程序运行效率。假设我们有一个 C++ 函数`add`,用于对两个数求和: @@ -108,21 +169,21 @@ int main() { 在 AI 框架的计算图编译器中,inline 的目标类似,但操作对象从“函数”变成了“子图”(subgraph)。假设我们有一个 Python 程序: ```python -from mindspore import Tensor, jit, ops +from mindspore -def f2(x: Tensor, y: Tensor): +def f2(x: mindspore.Tensor, y: mindspore.Tensor): return x * 0.5 + y -@jit -def f1(a: Tensor, b: Tensor, c: Tensor): +@mindspore.jit +def f1(a: mindspore.Tensor, b: mindspore.Tensor, c: mindspore.Tensor): x = f2(a, b) y = f2(a, c) return x + y # 创建3个shape=(2, 4)的随机值Tensor -a = ops.randn(2, 4) -b = ops.randn(2, 4) -c = ops.randn(2, 4) +a = mindspore.ops.randn(2, 4) +b = mindspore.ops.randn(2, 4) +c = mindspore.ops.randn(2, 4) out = f1(a, b, c) ``` @@ -189,59 +250,22 @@ subgraph @f1() { 通过 inline 将子图展开,编译器能够更清晰地识别跨子图的优化机会,除了公共子表达式消除 (CSE),还能够触发算子融合、内存管理等许多优化措施。因此 inline 是计算图编译器的一项重要优化机制,也是许多跨图优化的基础。 -### 冗余消除 +### 3 冗余消除 在传统编译器中,冗余消除包含了多种编译优化技术,旨在通过在编译期间识别出代码中存在冗余的部分并进行消除,达到减少不必要的计算,提高程序的执行效率的目的。 通常冗余代码可能是用户出于可读性等目的有意编写的,也可能仅仅是编码过程中的无心之举。此外,编译优化过程本身通过其它优化技术(如:代数化简、inline、公共子表达式消除等)产生的中间结果,也可能带来冗余消除的机会。 -冗余消除的技术有很多,本节挑选了其中常见的无用代码消除、不可达代码消除进行介绍。 - -1. **无用代码消除** - - 消除计算结果未被使用的代码。例如:下面的 C++ 代码中,变量 `c` 未被任何其它代码使用,编译器可以通过静态分析领域的数据流分析等技术,将计算 `int c = x * y` 的这行代码消除。 - - ```cpp - int func(x, y) { - int a = x + y; - int b = x - y; - int c = x * y; // 无用代码 - int d = a / b; - return d; - } - ``` - -2. **不可达代码消除** - - 消除未被有效控制流路径包含的代码。例如:下面的 C++ 代码中,编译器可以通过静态分析领域的控制流分析技术,分析代码的控制流图,识别到表达式 `1 < 0` 恒不成立,从而控制流 `1 < 0` 包含的代码在实际运行期间必定不会被执行,故可将该分支的代码消除。 - - ```cpp - int func(x, y) { - int a = x + y; - - int b; - if 1 < 0 { // 不可达分支 - b = x + y; - } else { - b = x - y; - } - - int d = a / b; - return d; - } - ``` - -MindSpore 图模式下冗余消除的目的及使用的技术也类似。与传统编译器不同的是,这些冗余优化技术是在 MindIR 上完成的。类似的,MindSpore 中常见的冗余消除技术有: +MindSpore冗余消除的目的及使用的技术与传统编译器类似。不同的是这些冗余优化是在 MindIR 上完成的。例如: 1. **无用代码消除** 假设有如下存在冗余计算的Python代码: ```python - import mindspore as ms - from mindspore.common import Tensor, jit - - @jit + import mindspore + + @mindspore.jit def func(x, y): a = x + y b = x - y @@ -249,12 +273,12 @@ MindSpore 图模式下冗余消除的目的及使用的技术也类似。与传 d = a / b return d - x = Tensor(20, ms.float32) - y = Tensor(10, ms.float32) + x = mindspore.tensor(20, mindspore.float32) + y = mindspore.tensor(10, mindspore.float32) out = func(x, y) ``` - MindSpore 图编译器会通过静态分析将 `@jit` 修饰的 Python 代码转换为 MindIR 的表示形式并消除其中冗余的 `c = x * y` 的计算,最终生成的 MindIR 如下: + MindSpore 图编译器会通过静态分析将 `@mindspore.jit` 修饰的 Python 代码转换为 MindIR 的表示形式并消除其中冗余的 `c = x * y` 的计算,最终生成的 MindIR 如下: ```text # Params: @@ -278,10 +302,9 @@ MindSpore 图模式下冗余消除的目的及使用的技术也类似。与传 假设有如下存在不可达路径的Python代码: ```python - import mindspore as ms - from mindspore.common import Tensor, jit + import mindspore - @jit + @mindspore.jit def func(x, y): a = x + y if 1 < 0: # 不可达分支 @@ -291,12 +314,12 @@ MindSpore 图模式下冗余消除的目的及使用的技术也类似。与传 d = a / b return d - x = Tensor(20, ms.float32) - y = Tensor(10, ms.float32) + x = mindspore.tensor(20, mindspore.float32) + y = mindspore.tensor(10, mindspore.float32) out = func(x, y) ``` - MindSpore 图编译器会通过静态分析将 `@jit` 修饰的 Python 代码转换为 MindIR 的表示形式并消除其中冗余的控制流分支 `1 < 0` 的代码,最终生成的 MindIR 如下: + MindSpore图编译器会通过静态分析将 `@mindspore.jit` 修饰的 Python 代码转换为 MindIR 的表示形式并消除其中冗余的控制流分支 `1 < 0` 的代码,最终生成的 MindIR 如下: ```text # Params: @@ -316,3 +339,109 @@ MindSpore 图模式下冗余消除的目的及使用的技术也类似。与传 ``` 冗余消除在编译优化中扮演着重要的角色,在不改变程序原语义的前提下,能够显著提高程序的执行效率,通过减少不必要的运行时计算节省计算资源。冗余消除通常还与其它编译优化技术结合使用以获得更多消除冗余代码的机会。 + +## 图优化(后端) + +当MindIR图经过前端优化完成后,需要进行进一步优化(包含目标硬件)。优化模式我们分为O0,O1,用参数jit_level表示 + - **jit_level=O0**: 只做基本的图切分优化,以及算子选择(硬件相关),优点是可以保证IR图的原始结构,编译速度较快。 + - **jit_level=O1**: 增加图优化和自动算子融合,编译性能有所损失,但模型开始训练后,效率较高 + +MindIR经过本轮优化后,会由runtime模块进行执行,涉及多级流水并发等技术,可参考[多级流水] + +### jit_level=O0 模式 + +O0模式的优化较少,基础的优化主要为后端LazyInline和No-task node执行优化。 + +- **LazyInline**: 主要思想是将函数调用的开销推迟到实际需要调用的时候,这样可以减少编译时的开销,提高编译效率。LazyInline在图编译阶段是将相同的子图结构复用,不展开放在图中,避免图规模较大导致影响编译性能。 + + ![jit_level_lazyinline](./images/multi_level_compilation/jit_level_lazyinline.png) + +- **No-task node执行优化**: No-task node指的是Reshape、ExpandDims、Squeeze、Flatten、FlattenGrad、Reformat等诸类算子没有计算逻辑,不修改内存排布,仅修改shape、format等信息。在图编译结束后,将No-task node转换成ref node,输出跟输入同地址,执行过程中跳过kernel launch,从而达到执行性能优化目的。 + + ![jit_level_no_task](./images/multi_level_compilation/jit_level_no_task.png) + +#### 算子选择 + +算子是深度学习框架中的基本执行单元,它们负责执行特定的计算任务,如矩阵乘法、卷积、池化等。算子选择需要综合考虑算子类型、数据类型、硬件平台和算子优化等因素,以选择最优的算子来实现模型运行效率最高。 + +MindSpore 在Ascend硬件的算子类型有aclnn kernel/aclop kernel/hccl kernel/cpu kernel,算子选择流程如下图所示: + +![jit_level_kernelselect](./images/multi_level_compilation/jit_level_kernelselect.png) + +1. 算子类型:首先根据算子类型选择为计算算子还是通信算子。 +2. 硬件平台:如果硬件上有对应算子,则优先选择硬件上的算子,否则选择CPU上的算子(异构),例如shape相关的计算算子可能只适合在CPU上支持,没有对应的硬件算子。 +3. 算子效率:ascend硬件由于aclnn算子较好的性能,因此计算类型算子如果有对应aclnn kernel,则优先选择aclnn kernel,否则就选择aclop kernel。 +4. 如果上述3步都未选择到算子,则为不支持的算子,算子选择失败报错。 + +#### 执行序编排 + +不同图遍历算法产生的执行序在执行性能跟内存上会有较大的差异,如图所示: +![jit_level_exec_order](./images/multi_level_compilation/jit_level_exec_order.png) + +- **BFS得到的执行序**:kernel1-> kernel2-> kernel4-> kernel5-> kernel3-> kernel6,内存峰值为5G(kernel3执行后可以把kernel1和kernel2的释放掉,则轮到kernel6执行的时候则能复用,因此kernel6 不用额外申请多的内存)。 +- **DFS得到的执行序**:kernel1-> kernel2-> kernel3-> kernel4-> kernel5-> kernel6,内存峰值为4G(kernel3执行后可以把kernel1和kernel2的释放掉,则轮到kernel4和kernel5执行的时候则能复用,因此kernel4和kernel5不用额外申请多的内存)。 + +执行序编排是在一定内存限制下求解最优算子并发的复杂性问题,不仅需要识别和利用计算图中的并发机会,以提升计算效率,还必须同时考虑多种限制条件,以确保系统的稳定性和高效性。 + +- 首先,优化模块需要解决求解最优算子并发的复杂性问题。由于计算图中的算子数量庞大且相互依赖,找到一个既能最大化并发又能保持计算图逻辑正确性的执行顺序是一个极具挑战性的任务。 +- 其次,内存限制是执行序优化中不可忽视的关键因素。增大并发虽然可以提升计算效率,但往往会显著增加峰值内存需求,从而可能导致内存溢出(OOM)错误,尤其是在资源受限的环境中。因此,优化模块必须权衡并发与内存使用之间的关系,确保在提升并发的同时,不会超出系统的内存容量。 +- MindSpore的执行序调整模块结合了基于规则和基于启发式策略的方式,提供bfs/dfs两种执行序编排算法[mindspore.jit(option={"exec_order":"bfs/dfs"})](https://www.mindspore.cn/docs/zh-CN/master/api_python/mindspore/mindspore.jit.html),以实现对计算图执行顺序的精细调整,从而在保证计算效率的同时,有效应对内存限制和系统稳定性等多重挑战。 + +### jit_level=O1 模式 + + 当前O1主要支持了图算融合优化。其主要思路是:在编译阶段,自动识别计算图中相邻的可融合节点,然后将其融合为更大粒度的可执行算子。通过图算融合,实现增加算子计算局部性、减少整体全局内存访存带宽开销等优化效果。通过对主流SOTA模型的实测验证,O1能够实现相比O0平均15%的性能加速。特别是对于访存密集型网络,O1优化效果更加显著。 + +#### 图算融合 + +MindSpore等主流AI计算框架对用户提供的算子通常是从用户可理解、易使用角度进行定义。每个算子承载的计算量不等,计算复杂度也各不相同。但从硬件执行角度看,这种天然的、基于用户角度的算子计算量划分,并不高效,也无法充分发挥硬件资源计算能力。主要体现在: + +1. 计算量过大、过复杂的算子,通常很难生成切分较好的高性能算子,从而降低设备利用率; +2. 计算量过小的算子,由于计算无法有效隐藏数据搬移开销,也可能会造成计算的空等时延,从而降低设备利用率; +3. 硬件Device通常为多核、众核结构,当算子shape较小或其他原因引起计算并行度不够时,可能会造成部分核的空闲,从而降低设备利用率。特别是基于专用处理器架构(Domain Specific Architecture,后文简称DSA)的芯片对这些因素更为敏感。如何最大化发挥硬件算力性能的同时使算子也能具备较好的易用性,一直以来是一个很大的挑战。 + +在AI框架设计方面,目前业界主流采用图层和算子层分层的实现方法。图层负责对计算图进行融合或重组,算子层负责将融合或重组后的算子编译为高性能的可执行算子。图层通常采用基于Tensor的High-Level IR的处理和优化,算子层则采用基于计算指令的Low-Level IR进行分析和优化。 这种人为分层处理显著增加了图、算两层进行协同优化的难度。 + +MindSpore在过去几年的技术实践中,采用了图算融合的技术来较好的解决了这个问题。NLP、推荐等不同类别的典型网络在使能图算融合后训练速度都有明显收益。主要原因之一就是这些网络中存在大量小算子组合,具有较多的融合优化机会。 + +#### 图算融合架构及整体流程 + +图算融合整体架构如下图所示。在图层主要思路是把复合算子打开,然后进行跨边界聚合和优化,最后进行Kernel算子拆分。主要步骤包括: + +1. Composite Expansion:将复合算子展开为基本算子,并构成Composite子图,方便进行后续的跨边界优化和算子拆分; +2. Cross-OP Aggregation:将相邻的基本算子或Composite子图进行聚合,从而构成更大的聚合子图,方便进行后续的跨边界优化和算子拆分; +3. High-Level Optimization:在上面两步得到的聚合子图的基础上,我们可以进行大量的跨边界优化,如代数化简、公共子表达式提取(CSE)等; +4. Kernel Partition:基于计算特征以及融合算子性能,对聚合计算子图进行算子拆分。 + +优化后的计算图会以一个个子图的方式传给MindSpore AKG继续进行后端优化、生成目标代码。 + +![graphkernel](./images/graphkernel.png) + +通过以上步骤,我们可以获得两方面性能收益: + +1. 不同算子之间的跨边界性能优化收益; +2. 通过对整个计算图进行重组拆分,得到最优粒度的融合算子。 + +#### 融合算子加速优化(MindSpore AKG) + +前文提到,在HPC、深度神经网络训练等场景中,图算融合优化可带来成倍的性能提升。但随着图算融合能力的不断增强,融合算子的开发成为了继续提升图算融合能力的瓶颈点。 + +融合算子的自动生成技术可以解决基于DSA开发融合算子编程门槛较高的问题,让程序员在算子开发过程中能够聚焦于算子的实现逻辑,无需关注后端优化,极大提高其开发效率。尤其对于后端硬件架构复杂以及存在复杂算子和融合算子的场景,算子自动生成技术更加关键。 + +因此,**MindSpore AKG基于多面体编译技术(Polyhedral Model),对融合算子的加速优化与自动生成**,能够帮助MindSpore的图算融合模块优化后的融合算子在**异构硬件平台**(GPU/Ascend)上自动生成高性能的kernel,提升MindSpore的训练性能。 + +架构及整体流程如下: + +![graphkernel_akg_overview](./images/graphkernel_akg_overview.png) + +MindSpore AKG的整体框架如上图所示: + +- IR规范化 + - MindSpore AKG的输入为MindSpore图算融合模块优化后的融合子图,通过TVM的Compute / IR Builder / Hybrid 等多种描述方式对子图中的算子进行表达。然后DSL会被转换为 Halide IR([Halide](https://halide-lang.org/),是常见的用于开发高性能图像处理和Array计算的语言,可作为中间表达解耦算法和优化)并进行 IR 规范化; + - 完成初步简化和优化后,Halide IR会被转化为Poly模块所需的调度树; +- Poly模块调度优化 + - 利用Polyhedral技术中的Pluto调度算法,实现循环的自动融合、自动重排等变换,为融合算子自动生成满足并行性、数据局部性的初始调度; + - 为快速适配不同硬件后端,Poly模块内的优化pass会分为硬件无关的通用优化与硬件相关的特定优化,编译时按照硬件特征拼接组合,实现异构硬件后端的快速适配。自动切分、自动映射以及自动内存提升等pass会根据不同硬件的架构性质给出不同的优化方式; +- 后端优化 + - 为了进一步提升算子的性能,我们针对不同硬件后端开发了相应的优化pass,如Ascend后端中实现数据对齐、指令映射,GPU后端中实现向量化存取,插入同步指令等,最终生成相应平台代码。 + +总结: MindSpore编译从图捕获模式,IR优化图算融合等各维度对AI模型代码进行优化,很多特性在易用性和性能方面的取舍也有一定挑战。我们也规划进一步分层解耦整个流程,避免黑盒运行,增加开发者理解的门槛。 \ No newline at end of file diff --git a/docs/mindspore/source_zh_cn/features/compile/graph_construction.ipynb b/docs/mindspore/source_zh_cn/features/compile/graph_construction.ipynb deleted file mode 100644 index a8ed39198a..0000000000 --- a/docs/mindspore/source_zh_cn/features/compile/graph_construction.ipynb +++ /dev/null @@ -1,273 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 构图(编译)\n", - "\n", - "[![下载Notebook](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_notebook.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/master/zh_cn/features/compile/mindspore_graph_construction.ipynb) [![下载样例代码](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_download_code.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/master/zh_cn/features/compile/mindspore_graph_construction.py) [![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/mindspore/source_zh_cn/features/compile/graph_construction.ipynb)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "MindSpore提供JIT(just-in-time)技术来进行性能优化。JIT模式会通过AST树解析、Python字节码解析或追踪代码执行的方式,将代码解析为一张中间表示图(IR,intermediate representation)。IR图作为该代码的唯一表示,编译器通过对该IR图的优化,来达到对代码的优化,提高运行性能。与动态图模式相对应,这种JIT的编译模式被称为静态图模式。\n", - "\n", - "基于JIT技术,MindSpore提供了动静结合的方法来提高用户的网络的运行效率。动静结合,即在整体运行为动态图的情况下,指定某些代码块以静态图的方式运行。按照静态图方式运行的代码块会采取先编译后执行的运行模式,在编译期对代码进行全局优化,来获取执行期的性能收益。用户可以通过`@jit`装饰器修饰函数,来指定其按照静态图的模式执行。有关`@jit`装饰器的相关文档请见[jit API文档](https://www.mindspore.cn/docs/zh-CN/master/api_python/mindspore/mindspore.jit.html#mindspore.jit)。\n", - "\n", - "MindSpore提供了三种JIT编译方式,分别通过ast、bytecode和trace的方式来构图。ast是通过AST树解析的方式,将用户手工标识需要按照ast方式执行的函数转换成静态图。bytecode则是通过对Python字节码的解析,在动态图中尽可能的构建静态图,无法转换为静态图的部分则会按照动态图进行执行,来达到动静结合的目的。trace是通过追踪Python代码执行的轨迹来构建静态图,当前属于实验性质的特性。后续介绍会详细说明三者原理的不同以及各自的特点。\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Ast\n", - "\n", - "在动态图模式下,用户可以通过`@jit(capture_mode=\"ast\")`装饰器修饰函数来让该函数以ast方式来执行。用ast方式修饰的函数,其内部使用的语法以及数据结构需要遵守静态图语法规范[静态图语法规范](https://www.mindspore.cn/tutorials/zh-CN/master/compile/static_graph.html)。ast方式通过源到源的方式来编译Python代码,先把模型定义的Python源码解析成抽象语法树,然后把抽象语法树解析为MindIR。例如下面的Python代码:\n", - "\n", - "```python\n", - "@jit\n", - "def foo(x, y):\n", - " z = x + y\n", - " return z\n", - "```\n", - "\n", - "它对应的抽象语法树如下:\n", - "\n", - "![抽象语法树](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/docs/mindspore/source_zh_cn/features/compile/images/ast.png)\n", - "\n", - "通过解析上面的抽象语法树,我们得到下面的MindIR:\n", - "\n", - "```text\n", - "%para1_x: \n", - "%para2_y: \n", - "\n", - "subgraph instance: foo\n", - "subgraph @foo() {\n", - " %0(CNode_17) = PrimFunc_Add(%para1_x, %para2_y)\n", - " : (, ) -> ()\n", - " Return(%0)\n", - " : ()\n", - "}\n", - "```\n", - "\n", - "**ast的使用方法**:\n", - "\n", - "用户可以通过`@jit`装饰器来指定函数以静态图的方式来执行,例如:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[4. 4. 4. 4.]\n", - " [4. 4. 4. 4.]]" - ] - } - ], - "source": [ - "import numpy as np\n", - "import mindspore as ms\n", - "from mindspore import ops\n", - "from mindspore import jit\n", - "from mindspore import Tensor\n", - "\n", - "@jit\n", - "def tensor_cal(x, y, z):\n", - " return ops.matmul(x, y) + z\n", - "\n", - "x = Tensor(np.ones(shape=[2, 3]), ms.float32)\n", - "y = Tensor(np.ones(shape=[3, 4]), ms.float32)\n", - "z = Tensor(np.ones(shape=[2, 4]), ms.float32)\n", - "ret = tensor_cal(x, y, z)\n", - "print(ret)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "上述用例中,tensor_cal函数被@jit装饰器修饰,该函数被调用时就会按照静态图的模式进行执行,以获取该函数执行期的性能收益。\n", - "\n", - "**ast的优点**:\n", - "\n", - "- 使用ast模式,用户的编程自主性更强,性能优化更精准,可以根据函数特征以及使用经验将网络的性能调至最优。\n", - "\n", - "**ast的限制**:\n", - "\n", - "- ast修饰的函数,其内部的语法必须严格遵守静态图语法来进行编程。\n", - "\n", - "**ast模式的使用建议**:\n", - "\n", - "- 相比于动态图执行,被`@jit`修饰的函数,在第一次调用时需要先消耗一定的时间进行静态图的编译。在该函数的后续调用时,若原有的编译结果可以复用,则会直接使用原有的编译结果进行执行。因此,使用@jit装饰器修饰会多次执行的函数通常会获得更多的性能收益。\n", - "\n", - "- 静态图模式的运行效率优势体现在其会将被@jit修饰函数进行全局上的编译优化,函数内含有的操作越多,优化的上限也就越高。因此`@jit`装饰器修饰的函数最好是内含操作很多的大代码块,而不应将很多细碎的、仅含有少量操作的函数分别打上jit标签。否则,则可能会导致性能没有收益甚至劣化。\n", - "\n", - "- MindSpore静态图绝大部分计算以及优化都是基于对Tensor计算的优化,因此我们建议被修饰的函数应该是那种用来进行真正的数据计算的函数,而不是一些简单的标量计算或者数据结构的变换。\n", - "\n", - "- 被`@jit`修饰的函数,若其输入存在常量,那么该函数每次输入值的变化都会导致重新编译,关于变量常量的概念请见[即时编译下的常量与变量](https://www.mindspore.cn/tutorials/zh-CN/master/compile/static_graph.html#%E5%8D%B3%E6%97%B6%E7%BC%96%E8%AF%91%E4%B8%8B%E7%9A%84%E5%B8%B8%E9%87%8F%E4%B8%8E%E5%8F%98%E9%87%8F)。因此,建议被修饰的函数以Tensor或者被Mutable修饰的数据作为输入。避免因多次编译导致的额外性能损耗。" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Bytecode\n", - "\n", - "除了ast,MindSpore提供另外一种静态化加速机制bytecode,用户可以通过`@jit(capture_mode=\"bytecode\")`装饰器修饰函数来让该函数以bytecode模式来执行。当bytecode识别到不支持进入静态图的语法时,会回退到Python执行而非直接编译报错。该功能同时兼顾性能和易用性,减少编译报错的发生。它基于Python字节码的分析,对Python的执行流进行图捕获,让可以以静态图方式运行的子图以静态图方式运行,并让Python语法不支持的子图以动态图方式运行,同时通过修改调整字节码的方式链接动静态图,达到动静混合执行。在满足易用性的前提下,尽可能地提高性能。\n", - "\n", - "**bytecode的运行原理**:\n", - "\n", - "1. 基于Python虚拟机_PyInterpreterState_SetEvalFrameFunc捕获Python函数的执行,采用上下文管理的方式捕获执行区域内的所有Python函数执行。\n", - "2. 按照当前的运行时输入参数结合函数字节码进行分析,构造控制流图(CFG)以及数据流图(DFG)。\n", - "3. 模拟进栈出栈操作,跟踪逐个字节码,根据栈输入,推导输出。Python3.7~Python3.11每条字节码都有对应的模拟实现,注意是推导输出的类型尺寸,而不是真正执行得到值,除非常量折叠。\n", - "4. 在模拟执行字节码的过程中,将推导结果和操作翻译成MindIR,最后,通过常量折叠,UD分析(删除无用的输入输出参数)等方式,优化静态图。\n", - "5. 在执行等效的静态图之前,对输入参数和优化过程中产生的看护Guard条件进行比对,根据运行时信息,选择匹配的静态图执行。\n", - "6. 动态管理看护Guard和静态图缓冲的匹配关系,对不常用的静态图缓冲进行回收,通过Symbolic Shape和Dynamic Shape优化静态图缓冲。\n", - "\n", - "bytecode的编译流程如下图所示\n", - "\n", - "![bytecode的编译流程](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/docs/mindspore/source_zh_cn/features/compile/images/bytecode.png)\n", - "\n", - "**bytecode的使用方式**:\n", - "\n", - "将jit的capture_mode参数设置为bytecode,即可将修饰函数的运行模式切换为bytecode,例如:\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[4. 4. 4. 4.]\n", - " [4. 4. 4. 4.]]" - ] - } - ], - "source": [ - "import numpy as np\n", - "import mindspore as ms\n", - "from mindspore import ops\n", - "from mindspore import jit\n", - "from mindspore import Tensor\n", - "\n", - "@jit(capture_mode=\"bytecode\")\n", - "def tensor_cal(x, y, z):\n", - " return ops.matmul(x, y) + z\n", - "\n", - "x = Tensor(np.ones(shape=[2, 3]), ms.float32)\n", - "y = Tensor(np.ones(shape=[3, 4]), ms.float32)\n", - "z = Tensor(np.ones(shape=[2, 4]), ms.float32)\n", - "ret = tensor_cal(x, y, z)\n", - "print(ret)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**bytecode的优点**:\n", - "\n", - "- 用户体验好,无需人工介入,用户编写的网络代码总是能够正常运行,静态图不能执行的代码会自动采用动态图运行。\n", - "- bytecode可以通过对字节码的变换,使得更多的语句进入静态图。用户无需感知或修改代码。\n", - "\n", - "**bytecode的限制**:\n", - "\n", - "- 用户无法明确对某些代码做性能加速,对于裂图较多的场景,性能加速的效果可能会不明显。" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Trace\n", - "\n", - "MindSpore也提供另外一种静态化加速机制trace,用户可以通过`@jit(capture_mode=\"trace\")`装饰器修饰函数来让该函数以trace模式来执行。在该模式下,代码会先以PyNative模式运行,在运行时调用的算子会被记录,并被捕获到计算图中。在后续执行该装饰器修饰的代码时,会直接执行第一次执行所构造出的计算图。该功能不会解析语法,只会捕获运行时调用的算子,因此不会有语法不支持报错的发生。它基于捕获运行PyNative模式时调用的算子,对Python的执行流进行图捕获,将捕获到的算子编入计算图中。没有对应算子的操作将无法生成节点,trace流程将只捕获该操作的返回值,在计算图中作为常量。生成的计算图以静态图的运行方式运行。\n", - "\n", - "**trace的使用方式**:\n", - "\n", - "将jit的capture_mode参数设置为trace,即可将修饰函数的运行模式切换为trace,例如:\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[4. 4. 4. 4.]\n", - " [4. 4. 4. 4.]]" - ] - } - ], - "source": [ - "import numpy as np\n", - "import mindspore as ms\n", - "from mindspore import ops\n", - "from mindspore import jit\n", - "from mindspore import Tensor\n", - "\n", - "@jit(capture_mode=\"trace\")\n", - "def tensor_cal(x, y, z):\n", - " return ops.matmul(x, y) + z\n", - "\n", - "x = Tensor(np.ones(shape=[2, 3]), ms.float32)\n", - "y = Tensor(np.ones(shape=[3, 4]), ms.float32)\n", - "z = Tensor(np.ones(shape=[2, 4]), ms.float32)\n", - "ret = tensor_cal(x, y, z)\n", - "print(ret)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**trace的优点**:\n", - "\n", - "- 构图能力强,只要代码有对应算子就能够入图,不需要额外适配。构建静态图时不会有语法不支持报错。\n", - "- 用户体验好,无需人工介入,用户编写的网络代码总是能够正常运行。\n", - "\n", - "**trace的限制**:\n", - "\n", - "- 无法感知控制流,多次运行时控制流会进入不同分支的场景无法保证正确性。\n", - "- 没有定义为算子的操作,如第三方库会在计算图中被固定为常量,多次运行无法保证正确性。" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python [conda env:base] *", - "language": "python", - "name": "conda-base-py" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/mindspore/source_zh_cn/features/compile/multi_level_compilation.md b/docs/mindspore/source_zh_cn/features/compile/multi_level_compilation.md deleted file mode 100644 index 0675dac4e7..0000000000 --- a/docs/mindspore/source_zh_cn/features/compile/multi_level_compilation.md +++ /dev/null @@ -1,139 +0,0 @@ -# 多级编译介绍(编译) - -[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/mindspore/source_zh_cn/features/compile/multi_level_compilation.md) - -## 背景 - -随着深度学习大模型时代的到来,网络规模越来越大,对图编译性能、执行性能和调试调优效率的挑战也越来越大。为此,MindSpore提出多级编译架构,提供O(n)多级编译执行模式,它们在图优化、算子融合、内存管理以及执行模式等方面有所不同,旨在提供图模式的多样性选择,用户可以根据自己的网络特点和需求,选择最适合的编译执行模式: - -1. O0模式:这是一个基础的编译执行模式,除必要影响功能的优化外,其他优化均关闭,使用单算子执行的执行方式。因此执行性能可能不是最优,但它的优点是可以保证图的原始结构,方便用户进行调试和理解,编译性能也较好。如下图中的Add和Mul单算子执行。 -2. O1模式:这个模式会进行一些基础的优化,比如常用图优化和自动算子融合优化,使用单算子执行的执行方式。相比O0,由于使能了融合优化,可以提高执行性能,但可能会影响到图的原始结构,因此编译性能和调试调优效率有所损失。如下图中的Add跟Mul融合成一个fused_op执行。 -3. O2模式:这是一个更高级的优化模式,目前没有实现,后续较为深层次的优化可使用该模式。 - -![jit_level_example](./images/multi_level_compilation/jit_level_example.png) - -## 多级编译架构概述 - -![jit_level_framework](./images/multi_level_compilation/jit_level_framework.png) - -1. 多级编译对外接口:通过[mindspore.jit(jit_level="O0/O1")](https://www.mindspore.cn/docs/zh-CN/master/api_python/mindspore/mindspore.jit.html#mindspore.jit)来配置多级编译级别,jit_level默认为O0,通常我们建议用户使用O0模式进行网络调试调优,调试就绪后,为了更好的性能可以一键开启O1运行网络。 -2. 后端图编译:根据配置的多级编译级别,选择不同的编译模式,O0为最基础的原生构图与编译,O1在O0基础增加了自动算子融合功能,主要功能有图优化、图算融合、算子选择、执行序编排,其中图算融合为O1模式下独有功能。 -3. 后端图执行:O0跟O1模式执行层面是一样的,均使用单算子方式调度执行,主要功能有多流并发、多级流水、HAL管理、内存管理。 - -## O0模式介绍 - -O0为基础的图编译执行模式,除必要影响功能的优化外,其他优化均关闭,使用原生的图结构进行编译和执行,方便调试调优,具备较好的编译性能。下面主要介绍后端图编译相关功能,后端图执行相关功能详见[运行时](https://www.mindspore.cn/docs/zh-CN/master/features/runtime/memory_manager.html)。 - -### 图优化 - -O0模式的图优化较少,基础的优化主要为后端LazyInline和No-task node执行优化。 - -- **后端LazyInline** - - **LazyInline**:主要思想是将函数调用的开销推迟到实际需要调用的时候,这样可以减少编译时的开销,提高编译效率。LazyInline在图编译阶段是将相同的子图结构复用,不展开放在图中,避免图规模较大导致影响编译性能。 - - ![jit_level_lazyinline](./images/multi_level_compilation/jit_level_lazyinline.png) - - **流水线(Pipeline)并行**:将神经网络中的算子切分成多个Stage,再把Stage映射到不同的设备上,使得不同设备去计算神经网络的不同部分。为了提升效率,流水线并行进一步将小批次(MiniBatch)切分成更细粒度的微批次(MicroBatch),在微批次中采用流水线式的调度,从而达到提升效率的目的。 - - **后端LazyInline**:由于Pipeline并行的MicroBatch切分会导致整个计算图扩张到MicroBatch的数量倍,从而导致模型规模巨大,编译性能时间较长(可能小时级别)。而这些Micro子图结构都是一样的,为了解决编译性能问题,LazyInline技术则非常契合,不过LazyInline带来的问题就是运行时无法采用最优的方式进行内存复用和流分配、无法做跨图的优化(内存优化、通信融合、算子融合等)等问题。为此,在图编译结束后,在图执行之前,将这些Micro子图做实际的节点Inline,以形成完整的全局整图,再通过图Inline后的内存优化、通信优化、冗余计算消除等方式,从而实现在编译性能、执行性能、执行内存方面都兼顾的目标。 - -- **No-task node执行优化** - - ![jit_level_no_task](./images/multi_level_compilation/jit_level_no_task.png) - - No-task node指的是Reshape、ExpandDims、Squeeze、Flatten、FlattenGrad、Reformat等诸类算子没有计算逻辑,不修改内存排布,仅修改shape、format等信息。在图编译结束后,将No-task node转换成ref node,输出跟输入同地址,执行过程中跳过kernel launch,从而达到执行性能优化目的。 - -### 算子选择 - -算子是深度学习框架中的基本执行单元,它们负责执行特定的计算任务,如矩阵乘法、卷积、池化等。算子选择需要综合考虑算子类型、数据类型、硬件平台和算子优化等因素,以选择最优的算子来实现深度学习任务。 - -MindSpore Ascend后端的算子类型有Aclnn kernel/Aclop kernel/Hccl kernel/Cpu kernel,算子选择流程如下图所示: - -![jit_level_kernelselect](./images/multi_level_compilation/jit_level_kernelselect.png) - -1. 算子类型:首先根据算子类型选择为计算算子还是通信算子。 -2. 硬件平台:如果硬件上有对应算子,则优先选择硬件上的算子,否则选择CPU上的异构算子,例如shape相关的计算算子可能只适合在CPU上支持,没有对应的硬件算子。 -3. 算子效率:Ascend上由于Aclnn算子较好的性能,因此计算类型算子如果有对应Aclnn kernel,则优先选择Aclnn kernel,否则就选择Aclop kernel。 -4. 如果上述3步都未选择到算子,则为不支持的算子,算子选择失败退出。 - -### 执行序编排 - -![jit_level_exec_order](./images/multi_level_compilation/jit_level_exec_order.png) - -不同图遍历算法产生的执行序在执行性能跟内存上会有较大的差异,如上图所示: - -- **BFS得到的执行序**:kernel1-> kernel2-> kernel4-> kernel5-> kernel3-> kernel6,内存峰值为5G(kernel3执行后可以把kernel1和kernel2的释放掉,则轮到kernel6执行的时候则能复用,因此kernel6 不用额外申请多的内存)。 -- **DFS得到的执行序**:kernel1-> kernel2-> kernel3-> kernel4-> kernel5-> kernel6,内存峰值为4G(kernel3执行后可以把kernel1和kernel2的释放掉,则轮到kernel4和kernel5执行的时候则能复用,因此kernel4和kernel5不用额外申请多的内存)。 - -执行序编排是在一定内存限制下求解最优算子并发的复杂性问题,不仅需要识别和利用计算图中的并发机会,以提升计算效率,还必须同时考虑多种限制条件,以确保系统的稳定性和高效性。 - -- 首先,优化模块需要解决求解最优算子并发的复杂性问题。由于计算图中的算子数量庞大且相互依赖,找到一个既能最大化并发又能保持计算图逻辑正确性的执行顺序是一个极具挑战性的任务。 -- 其次,内存限制是执行序优化中不可忽视的关键因素。增大并发虽然可以提升计算效率,但往往会显著增加峰值内存需求,从而可能导致内存溢出(OOM)错误,尤其是在资源受限的环境中。因此,优化模块必须权衡并发与内存使用之间的关系,确保在提升并发的同时,不会超出系统的内存容量。 -- MindSpore的执行序调整模块结合了基于规则和基于启发式策略的方式,提供bfs/dfs两种执行序编排算法[mindspore.jit(option={"exec_order":"bfs/dfs"})](https://www.mindspore.cn/docs/zh-CN/master/api_python/mindspore/mindspore.jit.html#mindspore.jit),以实现对计算图执行顺序的精细调整,从而在保证计算效率的同时,有效应对内存限制和系统稳定性等多重挑战。 - -## O1模式介绍 - -O1主要定位于在O0基础上实现通用、可泛化的AI编译优化,以支持大部分通用训练、推理场景的更好执行性能需求。 - -在当前阶段,O1主要支持了图算融合优化。其主要思路是:在静态图编译阶段,自动识别计算图中相邻的可融合节点,然后将其融合为更大粒度的可执行算子。通过图算融合,实现增加算子计算局部性、减少整体全局内存访存带宽开销等优化效果。通过对15+网络的实测验证,O1能够实现相比O0平均15%的性能加速。特别是对于访存密集型网络,O1优化效果更加显著。 - -### 图算融合 - -MindSpore等主流AI计算框架对用户提供的算子通常是从用户可理解、易使用角度进行定义。每个算子承载的计算量不等,计算复杂度也各不相同。但从硬件执行角度看,这种天然的、基于用户角度的算子计算量划分,并不高效,也无法充分发挥硬件资源计算能力。主要体现在: - -1. 计算量过大、过复杂的算子,通常很难生成切分较好的高性能算子,从而降低设备利用率; -2. 计算量过小的算子,由于计算无法有效隐藏数据搬移开销,也可能会造成计算的空等时延,从而降低设备利用率; -3. 硬件Device通常为多核、众核结构,当算子shape较小或其他原因引起计算并行度不够时,可能会造成部分核的空闲,从而降低设备利用率。特别是基于专用处理器架构(Domain Specific Architecture,后文简称DSA)的芯片对这些因素更为敏感。如何最大化发挥硬件算力性能的同时使算子也能具备较好的易用性,一直以来是一个很大的挑战。 - -在AI框架设计方面,目前业界主流采用图层和算子层分层的实现方法。图层负责对计算图进行融合或重组,算子层负责将融合或重组后的算子编译为高性能的可执行算子。图层通常采用基于Tensor的High-Level IR的处理和优化,算子层则采用基于计算指令的Low-Level IR进行分析和优化。 这种人为分层处理显著增加了图、算两层进行协同优化的难度。 - -MindSpore在过去几年的技术实践中,采用了图算融合的技术来较好的解决了这个问题。NLP、推荐等不同类别的典型网络在使能图算融合后训练速度都有明显收益。主要原因之一就是这些网络中存在大量小算子组合,具有较多的融合优化机会。 - -#### 图算融合架构及整体流程 - -图算融合整体架构如下图所示。在图层主要思路是把复合算子打开,然后进行跨边界聚合和优化,最后进行Kernel算子拆分。主要步骤包括: - -1. Composite Expansion:将复合算子展开为基本算子,并构成Composite子图,方便进行后续的跨边界优化和算子拆分; -2. Cross-OP Aggregation:将相邻的基本算子或Composite子图进行聚合,从而构成更大的聚合子图,方便进行后续的跨边界优化和算子拆分; -3. High-Level Optimization:在上面两步得到的聚合子图的基础上,我们可以进行大量的跨边界优化,如代数化简、公共子表达式提取(CSE)等; -4. Kernel Partition:基于计算特征以及融合算子性能,对聚合计算子图进行算子拆分。 - -优化后的计算图会以一个个子图的方式传给MindSpore AKG继续进行后端优化、生成目标代码。 - -![graphkernel](./images/graphkernel.png) - -通过以上步骤,我们可以获得两方面性能收益: - -1. 不同算子之间的跨边界性能优化收益; -2. 通过对整个计算图进行重组拆分,得到最优粒度的融合算子。 - -#### 融合算子加速优化(MindSpore AKG) - -前文提到,在HPC、深度神经网络训练等场景中,图算融合优化可带来成倍的性能提升。但随着图算融合能力的不断增强,融合算子的开发成为了继续提升图算融合能力的瓶颈点。 - -融合算子的自动生成技术可以解决基于DSA开发融合算子编程门槛较高的问题,让程序员在算子开发过程中能够聚焦于算子的实现逻辑,无需关注后端优化,极大提高其开发效率。尤其对于后端硬件架构复杂以及存在复杂算子和融合算子的场景,算子自动生成技术更加关键。 - -因此,**MindSpore AKG基于多面体编译技术(Polyhedral Model),对融合算子的加速优化与自动生成**,能够帮助MindSpore的图算融合模块优化后的融合算子在**异构硬件平台**(GPU/Ascend)上自动生成高性能的kernel,提升MindSpore的训练性能。 - -架构及整体流程如下: - -![graphkernel_akg_overview](./images/graphkernel_akg_overview.png) - -MindSpore AKG的整体框架如上图所示: - -- IR规范化 - - MindSpore AKG的输入为MindSpore图算融合模块优化后的融合子图,通过TVM的Compute / IR Builder / Hybrid 等多种描述方式对子图中的算子进行表达。然后DSL会被转换为 Halide IR([Halide](https://halide-lang.org/),是常见的用于开发高性能图像处理和Array计算的语言,可作为中间表达解耦算法和优化)并进行 IR 规范化; - - 完成初步简化和优化后,Halide IR会被转化为Poly模块所需的调度树; -- Poly模块调度优化 - - 利用Polyhedral技术中的Pluto调度算法,实现循环的自动融合、自动重排等变换,为融合算子自动生成满足并行性、数据局部性的初始调度; - - 为快速适配不同硬件后端,Poly模块内的优化pass会分为硬件无关的通用优化与硬件相关的特定优化,编译时按照硬件特征拼接组合,实现异构硬件后端的快速适配。自动切分、自动映射以及自动内存提升等pass会根据不同硬件的架构性质给出不同的优化方式; -- 后端优化 - - 为了进一步提升算子的性能,我们针对不同硬件后端开发了相应的优化pass,如Ascend后端中实现数据对齐、指令映射,GPU后端中实现向量化存取,插入同步指令等,最终生成相应平台代码。 - -### 其它图优化技术 - -除了图算融合之外,在后续版本中,O1可能会逐步扩展增加一些其它图优化技术。比如: - -1. KernelPacket:用于在动态shape场景对shape计算进行自动融合和优化; -2. 通算融合:将通信算子与计算算子进行融合。 diff --git a/docs/mindspore/source_zh_cn/features/overview.md b/docs/mindspore/source_zh_cn/features/overview.md index 4062caf187..95f47265c6 100644 --- a/docs/mindspore/source_zh_cn/features/overview.md +++ b/docs/mindspore/source_zh_cn/features/overview.md @@ -43,19 +43,17 @@ MindSpore实现了函数式微分编程,对可被微分求导的函数对象 同时,基于函数式编程范式,MindSpore提供了丰富高阶函数如vmap、shard等内置高阶函数功能。与微分求导函数grad一样,可以让开发者方便的构造一个函数或对象,作为高阶函数的参数。高阶函数经过内部编译优化,生成针对开发者函数的优化版本,实现如向量化变换、分布式并行切分等特点功能。 -### 动静统一的编程体验 +### 编程范式(动静结合) -传统AI框架主要有两种编程执行形态,静态图模式和动态图模式。 +传统AI框架主要有两种编程执行形态,静态图模式(graph mode)和动态图模式(pynative mode)。动态图模式又称eager mode。 -静态图模式会基于开发者调用的接口,在编译时生成神经网络的图结构,然后再执行图中涉及的计算操作。 +graph mode会在编译时生成神经网络的模型计算的图结构,然后再执行计算图。 -动态图模式,能有效解决静态图的编程门槛高问题,由于程序是按照代码的编写顺序执行,不做整图编译优化,相对性能优化空间较少,特别是面向DSA等专有硬件的优化具有较大挑战。 +pynative mode,由于程序是按照代码的编写顺序执行,符合python解释执行方式,易开发和调试。因为不做图编译优化,性能优化空间较少,特别是面向DSA等专有硬件的优化具有较大挑战。 -静态图模式,能有效感知神经网络各层算子间的关系,基于编译技术进行有效的编译优化以提升性能。但传统静态图需要开发者感知构图接口,组建或调试网络比较复杂,且难于与常用Python库、自定义Python函数进行穿插使用。 +MindSpore基于Python构建神经网络的图结构,相比于传统的graph mode,能有更易用、更灵活的表达能力。MindSpore创新性的构建源码转换能力,基于Python语句提取AST进行计算图构建,因此可以支持开发者使用的Python原生语法(条件/循环等)和其他操作,如元组(Tuple)、列表(List)以及Lambda表达来构建计算图,并对计算图进行自动微分。所以MindSpore能更好地兼容动态图和静态图的编程接口,在代码层面保持一致,如控制流写法等。 -MindSpore基于Python构建神经网络的图结构,相比于传统的静态图模式,能有更易用、更灵活的表达能力。MindSpore创新性的构建源码转换能力,基于Python语句提取AST进行计算图构建,因此可以支持开发者使用的Python原生语法(条件/循环等)和其他操作,如元组(Tuple)、列表(List)以及Lambda表达来构建计算图,并对计算图进行自动微分。所以MindSpore能更好地兼容动态图和静态图的编程接口,在代码层面保持一致,如控制流写法等。 - -原生Python表达可基于Python控制流关键字,直接使能静态图模式的执行,使得动静态图的编程统一性更高。同时开发者基于MindSpore的接口,可以灵活的对Python代码片段进行动静态图模式控制。即可以将程序局部函数以静态图模式执行([mindspore.jit](https://www.mindspore.cn/docs/zh-CN/master/api_python/mindspore/mindspore.jit.html))而同时其他函数按照动态图模式执行。从而使得在与常用Python库、自定义Python函数进行穿插执行使用时,开发者可以灵活指定函数片段进行静态图优化加速,而不牺牲穿插执行的编程易用性。 +原生Python表达可基于Python控制流关键字,直接使能静态图模式的执行,使得动静态图的编程统一性更高。同时开发者基于MindSpore的接口,可以灵活的对Python代码片段进行动静态图模式控制。即可以将程序局部函数以静态图模式执行([mindspore.jit](https://www.mindspore.cn/docs/zh-CN/master/api_python/mindspore/mindspore.jit.html))而其他函数按照动态图模式执行。从而使得在与常用Python库、自定义Python函数进行穿插执行使用时,开发者可以灵活指定函数片段进行静态图优化加速,而不牺牲穿插执行的编程易用性。 ### 分布式并行 @@ -67,11 +65,11 @@ MindSpore在并行化策略搜索中引入了张量重排布技术(Tensor Redi 同时MindSpore还提供了流水线并行、优化器并行、重计算等多种并行策略供开发者使用。 -### 硬件高性能发挥 +### 编译 MindSpore基于编译技术,提供了丰富的硬件无关优化,如IR融合、代数化简、常数折叠、公共子表达式消除等。同时针对NPU、GPU等不同硬件,也提供各种硬件优化能力,从而更好的发挥硬件的大规模计算加速能力。 -#### [图算融合](https://www.mindspore.cn/docs/zh-CN/master/features/compile/multi_level_compilation.html#图算融合) +#### [多级编译架构](https://www.mindspore.cn/docs/zh-CN/master/features/compile/compilation_guide_zh.html#图算融合) MindSpore等主流AI计算框架对开发者提供的算子通常是从开发中可理解、易使用角度进行定义。每个算子承载的计算量不等,计算复杂度也各不相同。但从硬件执行角度看,这种天然的、基于用开发者角度的算子计算量划分,并不高效,也无法充分发挥硬件资源计算能力。主要体现在: @@ -101,6 +99,6 @@ MindSpore是训推一体的AI框架,同时支持训练和推理等功能。同 MindSpore按照实际执行环境和业务需求,提供多种规格的版本形态,支持部署在云端、服务器端、手机等嵌入式设备端以及耳机等超轻量级设备端上的部署执行。 -### [三方硬件接入](https://www.mindspore.cn/docs/zh-CN/master/features/runtime/pluggable_device.html) +### 三方硬件接入 MindSpore基于统一MindIR构建了开放式AI架构,支持第三方芯片插件化、标准化、低成本快速对接,可接入GPU系列芯片亦可接入各类DSA芯片。MindSpore提供Kernel模式对接和Graph模式对接两种芯片接入方式,芯片产商可根据自身特点进行接入方式选择。 -- Gitee