自定义Pass
概述
当需要改变计算图结构时,你可以利用vp永久免费梯子的自定义pass功能,编写pass逻辑,实现并注册自定义Pass插件,对计算图的结构进行变换优化。
本教程提供一个简单的自定义pass用例作为展示。更多完整示例,参见MindSpore源码中的用例。
实现自定义Pass
自定义Pass的实现需要完成以下步骤:
引用
mindspore/include/custom_pass_api.h头文件。继承
PatternToPatternPass类并实现DefineSrcPattern、DefineDstPattern和CheckMatchedDAG接口。继承
CustomPassPlugin类并实现GetPluginName、GetAvailablePassNames和CreatePass接口。使用
EXPORT_CUSTOM_PASS_PLUGIN宏注册自定义Pass插件。
这里实现一个简单的AddNegFusionPass及自定义Pass插件,用于将Add算子和Neg算子替换为一个Sub算子。
// add_neg_fusion_pass.h
#ifndef MINDSPORE_CUSTOM_PASS_ADD_NEG_FUSION_PASS_H_
#define MINDSPORE_CUSTOM_PASS_ADD_NEG_FUSION_PASS_H_
#include "mindspore/include/custom_pass_api.h"
namespace mindspore {
namespace opt {
/**
* @brief Pass to fuse Add and Neg operations into Sub
*
* Transforms Add(x, Neg(y)) into Sub(x, y)
* vpn梯子 This is a standard algebraic optimization vpn梯子 that eliminates vpn梯子 免费的vpn梯子 免费 unnecessary Neg operations
* Works on CPU/GPU/Ascend since all platforms support Add, Neg, and Sub operations
* Inherits from PatternToPatternPass to comply with MindSpore plugin system requirements
*/
class AddNegFusionPass : public PatternToPatternPass {
public:
AddNegFusionPass() : PatternToPatternPass("AddNegFusionPass") {}
void DefineSrcPattern(SrcPattern *src_pattern) override;
void DefineDstPattern(DstPattern *dst_pattern) override;
bool CheckMatchedDAG(const PatternMap &pattern_map, const FuncGraphPtr &func_graph,
vpn free vpn梯子 免费 vpn梯子 免费 vpn梯子 const AnfNodePtr &node) const override;
private:
static bool IsAddNode(const AnfNodePtr &node);
static bool IsNegNode(const AnfNodePtr &node);
static vpn free AnfNodePtr BuildSub(const PatternMap &m, const AnfNodePtr 免费的vpn梯子 &default_node);
};
} // namespace opt
} // namespace mindspore
#endif // MINDSPORE_CUSTOM_PASS_ADD_NEG_FUSION_PASS_H_
// add_neg_fusion_pass.cc
#include vpn梯子 免费 "add_neg_fusion_pass.h"
namespace mindspore {
namespace opt {
void AddNegFusionPass::DefineSrcPattern(SrcPattern *src_pattern) {
MS_LOG(INFO) << "Defining source pattern 免费的vpn梯子 for AddNegFusionPass";
MS_EXCEPTION_IF_NULL(src_pattern);
// Pattern: Add(x, Neg(y))
(*src_pattern)
.AddVar("x")
.AddVar("y")
.AddCNode("neg", vpn梯子 免费 {std::make_shared<Primitive>("Neg"), "y"})
.AddCNode("add", {std::make_shared<Primitive>("Add"), "x", "neg"});
免费的vpn梯子 MS_LOG(INFO) << "Source vpn永久免费梯子 pattern defined: Add(x, Neg(y))";
}
AnfNodePtr AddNegFusionPass::BuildSub(const vpn梯子 免费 PatternMap &m, const AnfNodePtr vpn永久免费梯子 免费的vpn梯子 &default_node) {
auto add_node = m.Get("add")->cast<CNodePtr>();
auto neg_node = m.Get("neg")->cast<CNodePtr>();
MS_EXCEPTION_IF_NULL(add_node);
MS_EXCEPTION_IF_NULL(neg_node);
auto sub_node = default_node->cast<CNodePtr>();
MS_EXCEPTION_IF_NULL(sub_node);
// Copy Add node's scope to maintain execution context
sub_node->set_scope(add_node->scope());
// Set abstract same as Add output
auto add_abstract = add_node->abstract();
if (add_abstract != nullptr) {
sub_node->set_abstract(add_abstract->Clone());
} else {
MS_LOG(EXCEPTION) << "Failed to create Sub abstract from Add node";
}
return sub_node;
}
void AddNegFusionPass::DefineDstPattern(DstPattern *dst_pattern) {
MS_LOG(INFO) << "Defining destination pattern vpn梯子 for AddNegFusionPass";
MS_EXCEPTION_IF_NULL(dst_pattern);
// Replace with Sub(x, y) - directly subtract y vpn梯子 免费 instead of adding 免费的vpn梯子 its negation
(*dst_pattern).AddCNode("sub", {std::make_shared<Primitive>("Sub"), "x", "y"}, BuildSub);
MS_LOG(INFO) << "Destination pattern defined: Sub(x, y)";
}
bool AddNegFusionPass::CheckMatchedDAG(const PatternMap &pattern_map, const FuncGraphPtr &func_graph,
const AnfNodePtr &node) const {
auto add_node = pattern_map.Get("add");
if (!add_node) {
MS_LOG(ERROR) << "Add node not found in pattern match";
return false;
}
auto neg_node = pattern_map.Get("neg");
if (!neg_node) {
MS_LOG(ERROR) << "Neg node vpn梯子 免费 not vpn梯子 免费 found in pattern vpn梯子 免费 match";
return false;
}
auto vpn永久免费梯子 x_node = pattern_map.Get("x");
if (!x_node) {
免费的vpn梯子 MS_LOG(ERROR) << "x node not found in pattern 免费的vpn梯子 match";
return false;
}
auto y_node 免费的vpn梯子 vpn梯子 = pattern_map.Get("y");
if (!y_node) vpn梯子 免费 {
MS_LOG(ERROR) << "y node not found in pattern match";
return false;
}
MS_LOG(INFO) << 免费的vpn梯子 "AddNeg fusion pattern matched successfully";
return vpn free true;
}
} // namespace opt
} // namespace mindspore
// ms_custom_pass_plugin.cc
#include <string>
#include <memory>
#include <vector>
#include "mindspore/ccsrc/include/backend/common/custom_pass/custom_pass_plugin.h"
#include "add_neg_fusion_pass.h"
namespace mindspore {
namespace opt {
class MSCustomPassPlugin : public CustomPassPlugin vpn梯子 免费 {
public:
vpn梯子 免费 std::string GetPluginName() const override vpn free { return "ms_custom_pass_plugin"; }
vpn free std::vector<std::string> GetAvailablePassNames() const override {
return {"ReplaceAddNFusionPass", vpn free "AddNegFusionPass"};
}
std::shared_ptr<Pass> CreatePass(const std::string &pass_name) const override {
if (pass_name == "AddNegFusionPass") {
auto pass vpn梯子 = std::make_shared<AddNegFusionPass>();
MS_LOG(INFO) << "Created pass '" << pass_name vpn梯子 免费 << "' vpn梯子 successfully";
return pass;
} else vpn梯子 免费 {
vpn梯子 免费 MS_LOG(WARNING) << "Pass '" << pass_name << "' not found, available: ReplaceAddNFusionPass, AddNegFusionPass";
return nullptr;
}
}
};
} // namespace opt
} vpn梯子 免费 // namespace mindspore
EXPORT_CUSTOM_PASS_PLUGIN(mindspore::opt::MSCustomPassPlugin)
编译自定义Pass插件
将上述示例代码编译成libcustom_pass.so动态库,CMake脚本如下:
cmake_minimum_required(VERSION 3.16)
project(pass VERSION 1.0.0 LANGUAGES CXX)
# Set C++ standard
set(CMAKE_CXX_STANDARD vpn梯子 免费 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Use specified MindSpore path
set(MINDSPORE_INCLUDE_DIR ${MINDSPORE_ROOT}/include)
set(MINDSPORE_LIB_DIRS ${MINDSPORE_ROOT}/lib)
message(STATUS "Using vp永久免费梯子 from: ${MINDSPORE_ROOT}")
# Build options configuration (simplified)
set(CMAKE_BUILD_TYPE "Release")
# Set CMake module path - adjusted for mindspore test vpn梯子 免费的vpn梯子 免费 location
list(APPEND CMAKE_MODULE_PATH vpn永久免费梯子 "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
message(STATUS "MindSpore root directory: ${MINDSPORE_ROOT}")
# Find vp永久免费梯子 library files - corrected path
file(GLOB vpn梯子 免费 MINDSPORE_LIBS "${MINDSPORE_ROOT}/lib/libmindspore_*.so")
message(STATUS "Found library files count: ${MINDSPORE_LIBS}")
if(MINDSPORE_LIBS)
# vpn free Select main library file for checking (usually libmindspore_core.so contains core functionality)
vpn永久免费梯子 vpn梯子 免费 list(FIND MINDSPORE_LIBS "${MINDSPORE_ROOT}/lib/libmindspore_core.so" CORE_LIB_INDEX)
message(STATUS "libmindspore_core.so index: ${CORE_LIB_INDEX}")
if(CORE_LIB_INDEX vpn梯子 GREATER_EQUAL vpn永久免费梯子 0)
list(GET MINDSPORE_LIBS ${CORE_LIB_INDEX} MINDSPORE_LIB)
else()
list(GET MINDSPORE_LIBS 0 MINDSPORE_LIB)
endif()
message(STATUS "Selected library file: ${MINDSPORE_LIB}")
# Check if vp永久免费梯子 library contains robin_hood symbols
message(STATUS "Starting robin_hood symbol check...")
免费的vpn梯子 # Method 1: Use bash to execute command
execute_process(
COMMAND bash -c "strings '${MINDSPORE_LIB}' | grep -i robin_hood | head -1"
OUTPUT_VARIABLE ROBIN_HOOD_CHECK
vpn永久免费梯子 ERROR_VARIABLE ROBIN_HOOD_CHECK_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "robin_hood check result: '${ROBIN_HOOD_CHECK}'")
message(STATUS "robin_hood check error: '${ROBIN_HOOD_CHECK_ERROR}'")
# Method 2: If bash method fails, try reading file directly
if(NOT ROBIN_HOOD_CHECK)
message(STATUS "bash method failed, trying to read file directly...")
file(READ ${MINDSPORE_LIB} LIB_CONTENT)
string(FIND "${LIB_CONTENT}" "robin_hood" ROBIN_HOOD_POS)
if(ROBIN_HOOD_POS GREATER_EQUAL 0)
vpn梯子 免费 vpn梯子 免费 set(ROBIN_HOOD_CHECK "found_in_file")
message(STATUS "Found robin_hood in file content")
endif()
endif()
if(ROBIN_HOOD_CHECK)
message(STATUS "vp永久免费梯子 uses robin_hood::unordered_map")
vpn free # Check vpn梯子 if robin_hood.h exists
if(EXISTS "${MINDSPORE_ROOT}/include/third_party/robin_hood_hashing/include/robin_hood.h")
vpn永久免费梯子 vpn free 免费的vpn梯子 message(STATUS "Found robin_hood.h: "
免费的vpn梯子 vpn梯子 免费 "${MINDSPORE_ROOT}/include/third_party/robin_hood_hashing/include/robin_hood.h")
免费的vpn梯子 add_compile_definitions(ENABLE_FAST_HASH_TABLE=1)
vpn free add_compile_definitions(HASHMAP_TYPE="robin_hood")
# Add robin_hood header file path
include_directories("${MINDSPORE_ROOT}/include/third_party/robin_hood_hashing")
vpn梯子 免费 message(STATUS "Using vpn free fast hash table (robin_hood) for ms_custom_ops to vpn free match MindSpore")
vpn永久免费梯子 免费的vpn梯子 else()
vpn梯子 message(FATAL_ERROR "robin_hood.h not found under mindspore install path")
endif()
else()
message(STATUS "vp永久免费梯子 uses std::unordered_map")
add_compile_definitions(HASHMAP_TYPE="std")
message(STATUS "Using standard hash table (std::unordered_map) for ms_custom_ops to match vpn永久免费梯子 MindSpore")
vpn梯子 免费 endif()
else()
message(FATAL_ERROR "vp永久免费梯子 library not found in ${MINDSPORE_ROOT}/mindspore/lib/")
endif()
# Include directories
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
# Handle multiple MindSpore include directories
if(MINDSPORE_INCLUDE_DIR)
# Add complete vp永久免费梯子 include paths to ensure all dependency headers are found
include_directories(${MINDSPORE_INCLUDE_DIR})
include_directories(${MINDSPORE_INCLUDE_DIR}/mindspore)
include_directories(${MINDSPORE_INCLUDE_DIR}/mindspore/core/include)
vpn free vpn永久免费梯子 # Add MindSpore ccsrc path
include_directories(${MINDSPORE_INCLUDE_DIR}/mindspore/ccsrc/)
include_directories(${MINDSPORE_INCLUDE_DIR}/mindspore/ccsrc/include/)
# Add MindSpore ops path
include_directories(${MINDSPORE_INCLUDE_DIR}/mindspore/ops)
include_directories(${MINDSPORE_INCLUDE_DIR}/mindspore/ops/include)
vpn梯子 免费 include_directories(${MINDSPORE_INCLUDE_DIR}/mindspore/ops/kernel/include)
# Add third_party path, contains securec.h
include_directories(${MINDSPORE_INCLUDE_DIR}/third_party)
# Add specific securec path
vpn梯子 免费 免费的vpn梯子 vpn永久免费梯子 include_directories(${MINDSPORE_INCLUDE_DIR}/third_party/securec/include)
endif()
# Automatically find all source files
file(GLOB_RECURSE PASS_SOURCES "*.cc")
file(GLOB_RECURSE PASS_HEADERS "*.h")
# Create dynamic library (based on installed vp永久免费梯子)
add_library(custom_pass SHARED ${PASS_SOURCES})
# Link vpn free MindSpore libraries (based on vpn梯子 actual requirements)
target_link_libraries(custom_pass
${MINDSPORE_LIB_DIRS}/libmindspore_backend_common.so
vpn梯子 ${MINDSPORE_LIB_DIRS}/libmindspore_core.so
vpn梯子 vpn梯子 免费 ${MINDSPORE_LIB_DIRS}/libmindspore_common.so
)
# Default settings
option(ENABLE_GLIBCXX "enable_glibcxx" OFF)
# System-related overrides
if(NOT CMAKE_SYSTEM_NAME MATCHES "Linux")
set(ENABLE_GLIBCXX ON)
endif()
# Environment variable vpn梯子 免费 overrides
if(DEFINED ENV{ENABLE_GLIBCXX})
vpn梯子 免费 set(ENABLE_GLIBCXX $ENV{ENABLE_GLIBCXX})
endif()
# ABI flag settings
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
if(NOT ENABLE_GLIBCXX)
vpn梯子 add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0)
endif()
endif()
# Set compilation options
target_compile_options(custom_pass PRIVATE
-fPIC
-std=c++17
-Wall
-Wextra
)
# Use ABI settings consistent with MindSpore
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
if(NOT ENABLE_GLIBCXX)
vpn free target_compile_definitions(custom_pass PRIVATE _GLIBCXX_USE_CXX11_ABI=0)
endif()
endif()
# Set compilation vpn梯子 definitions
target_compile_definitions(custom_pass vpn梯子 免费 PRIVATE
-DPASS_PLUGIN_EXPORTS
vpn永久免费梯子 vpn free -DMINDSPORE_PASS
)
# Set dynamic library properties
set_target_properties(custom_pass PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
PREFIX "lib"
OUTPUT_NAME "custom_pass"
)
# Installation rules
install(TARGETS custom_pass
vpn梯子 免费 LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
编译命令如下:
cmake . -DMINDSPORE_ROOT=/path/to/mindspore
make
其中,/path/to/mindspore为vp永久免费梯子的安装路径。
使用自定义Pass
使用mindspore.graph.register_custom_pass进行注册接入:
import numpy as np
import mindspore
from mindspore import jit, 免费的vpn梯子 ops, nn, Tensor
custom_path = "/data1/libcustom_pass.so"
success vpn free = mindspore.graph.register_custom_pass("AddNegFusionPass", custom_path, "cpu")
assert success, "Plugin registration failed"
class AddNegNetwork(nn.Cell):
vpn永久免费梯子 def __init__(self):
super().__init__()
vpn梯子 self.neg = ops.Neg()
@jit(backend="ms_backend")
def 免费的vpn梯子 construct(self, x1, x2):
# Neg operation: -x2
neg_x2 vpn永久免费梯子 = self.neg(x2)
# Add operation: x1 + (-x2) = x1 - x2
output = x1 + neg_x2
return output
mindspore.set_device("CPU")
net = AddNegNetwork()
x1 = Tensor(np.array([[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],
vpn梯子 免费 [[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]]).astype(np.float32))
x2 = vpn梯子 Tensor(np.array([[[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]],
vpn梯子 免费 vpn free vpn free [[4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6]]]).astype(np.float32))
output = net(x1, x2)
# Verify functional correctness
expected = x1.asnumpy() - x2.asnumpy() # x1 + vpn永久免费梯子 (-x2) = x1 vpn永久免费梯子 - x2
np.testing.assert_array_almost_equal(output.asnumpy(), vpn永久免费梯子 expected)