昇腾社区首页
中文
注册
开发者
下载

Session到GeSession的迁移指导

本节旨在指导用户从Session类迁移到新引入的GeSession类。GeSession是对原有Session类的重构和优化,主要变化包括:

  • 简化编译和加载流程:不需要手动调用CompileGraph和LoadGraph(除非需要显式控制)。详见编译和运行接口变化
  • 统一执行接口的参数类型:所有运行接口的输入输出从ge::Tensor改为gert::Tensor。详见Tensor类型变化
  • 优化接口命名和参数类型。详见接口变化

其他变更点注意事项:

  • 头文件和库文件变化:头文件从ge/ge_api.h改为ge/ge_api_v2.h,库文件从libge_runner.so改为libge_runner_v2.so。详见库链接变化
  • 异步生命周期:使用RunGraphAsync时,inputs必须保持有效直到callback被调用。详见Tensor生命周期说明
  • 执行模式互斥:三种运行模式不能混用。详见编译和运行接口变化

下面按照分类详细介绍上述变更点。

库链接变化

表1 库链接变化

类别

Session

GeSession

库文件

libge_runner.so

libge_runner_v2.so

头文件

ge/ge_api.h

ge/ge_api_v2.h

接口变化

Session 接口

GeSession 接口

迁移说明

GEInitialize(options)

GEInitializeV2(options)

新增接口

GEFinalize()

GEFinalizeV2()

新增接口

GEGetErrorMsg()

GEGetErrorMsgV3()

新增接口

GEGetWarningMsg()

GEGetWarningMsgV3()

新增接口

Session(options)

GeSession(options)

构造函数基本一致,但只提供了ABI兼容的std::map<AscendString, AscendString>类型版本

~Session()

~GeSession()

析构函数,无变化

AddGraph(uint32_t, const Graph&)

AddGraph

(uint32_t, const Graph&)

接口保持一致

AddGraph(uint32_t, const Graph&, options)

AddGraph

(uint32_t, const Graph&, options)

只提供了ABI兼容的std::map<AscendString, AscendString>类型版本

AddGraphWithCopy

AddGraphClone

重命名,功能相同

RemoveGraph

RemoveGraph

无变化

BuildGraph

CompileGraph

重命名,功能相同。GeSession的CompileGraph支持Variable

CompileGraph

CompileGraph

合并了BuildGraph和CompileGraph的功能

LoadGraph

LoadGraph

接口基本一致,但GeSession中会自动检查是否需要先CompileGraph

RunGraph

RunGraph

重要变化输入输出从ge::Tensor改为gert::Tensor

RunGraphWithStreamAsync

RunGraphWithStreamAsync

重要变化:输入输出从ge::Tensor改为gert::Tensor;CompileGraph和LoadGraph可省略

ExecuteGraphWithStreamAsync

RunGraphWithStreamAsync

Session中的ExecuteGraphWithStreamAsync(使用 gert::Tensor)合并到GeSession的RunGraphWithStreamAsync

RunGraphAsync

RunGraphAsync

要变化:输入输出从ge::Tensor改为gert::Tensor;回调函数签名从RunAsyncCallback改为RunAsyncCallbackV2

RegisterCallBackFunc

RegisterCallBackFunc

回调函数签名变化,使用RunCallback类型

GetCompiledGraphSummary

GetCompiledGraphSummary

无变化

SetGraphConstMemoryBase

SetGraphConstMemoryBase

无变化

UpdateGraphFeatureMemoryBase

UpdateGraphFeatureMemoryBase

无变化

SetGraphFixedFeatureMemoryBase

SetGraphFixedFeatureMemoryBaseWithType

接口名称变化,增加了type参数

UpdateGraphRefreshableFeatureMemoryBase

UpdateGraphRefreshableFeatureMemoryBase

无变化

RegisterExternalAllocator

RegisterExternalAllocator

无变化

UnregisterExternalAllocator

UnregisterExternalAllocator

无变化

IsGraphNeedRebuild

IsGraphNeedRebuild

无变化

GetSessionId

GetSessionId

无变化

-

GetCompiledModel

新增接口:获取编译后的模型数据

GetVariables

-

已删除,无替代接口

ShardGraphsToFile

-

已删除,图分片功能不再提供

ShardGraphs

-

已删除,图分片功能不再提供

SaveGraphsToPb

-

已删除,保存图到pb文件功能不再提供

PaRemapped

-

已删除,虚拟内存重映射功能不再提供

Tensor类型变化

所有运行接口的输入输出从ge::Tensor改为gert::Tensor,详情如下:

  • 命名空间变化

    特性

    ge::Tensor

    gert::Tensor

    命名空间

    ge

    gert

    数据结构

    使用std::shared_ptr<TensorImpl>管理内部实现

    POD类型(Plain Old Data),所有数据内联存储

    内存布局

    间接访问,通过impl_指针

    扁平化布局,支持直接memcpy

    Placement支持

    通过TensorDesc设置 Placement

    支持多种Placement类型

    拷贝行为

    浅拷贝(shared_ptr语义)

    浅拷贝,指针共享

    性能

    一般

    高性能

    适用场景

    图构建阶段

    运行时执行

  • 数据结构变化

    ge::Tensor内部结构

    gert::Tensor内部结构

    class Tensor {
    private:
      std::shared_ptr<TensorImpl> impl_;  // 使用智能指针管理
    };
    • 使用 shared_ptr 管理 TensorImpl
    • 拷贝时共享底层实现
    • 数据通过 TensorDesc 描述
    class Tensor {
    private:
      StorageShape storage_shape_;        // Shape信息
      StorageFormat storage_format_;      // Format信息
      TensorVersion version_;             // 版本
      uint8_t reserved_[3];               // 预留字段
      ge::DataType data_type_;            // 数据类型
      TensorData tensor_data_;            // 数据指针和placement
      uint8_t reserved_field_[40];        // 预留字段
    };
    • 所有字段直接内联在对象中
    • 是标准布局类型(std::is_standard_layout)

下面给出gert::Tensor生命周期的说明以及构造gert::Tensor的方法:

  • Tensor生命周期说明
    • RunGraph接口
      1
      2
      3
      4
      std::vector<gert::Tensor> inputs = ...;
      std::vector<gert::Tensor> outputs;
      session->RunGraph(graph_id, inputs, outputs);
      // inputs和outputs在调用完成后可以安全释放
      
    • RunGraphWithStreamAsync接口
      1
      2
      3
      4
      5
      6
      // 注意:可以不先调用CompileGraph和LoadGraph,会自动处理
      std::vector<gert::Tensor> inputs = ...;
      std::vector<gert::Tensor> outputs;
      session->RunGraphWithStreamAsync(graph_id, stream, inputs, outputs);
      // inputs和outputs在stream同步之前不能释放
      // 需要调用aclrtSynchronizeStream或其他同步机制
      
    • RunGraphAsync接口(重要)
      using RunAsyncCallbackV2 = std::function<void(Status, std::vector<gert::Tensor>&)>;
      std::vector<gert::Tensor> inputs = ...;
      session->RunGraphAsync(graph_id, inputs,
          [](Status ret, std::vector<gert::Tensor>& outputs) {
              // 处理输出
          });
      // 重要:inputs不能立即释放!
      // 必须等到callback函数被调用后才能释放inputs
      // 因为模型执行的时候会读取inputs、callback被调用可保证模型执行完成
  • 构造gert::Tensor的方法
    • 方法1: 使用TensorData构造(推荐)
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      #include "exe_graph/runtime/tensor.h"
      #include "acl_rt.h"
      
      // 构造 Host Tensor
      void* host_buf = nullptr;
      aclError ret = aclrtMallocHost(&host_buf, data_len);  // 分配Host内存
      if (ret != ACL_ERROR_NONE) {
          // 处理错误
      }
      
      // 使用TensorData构造
      gert::TensorData td(host_buf, nullptr, data_len, gert::kOnHost);
      gert::Tensor tensor;
      tensor.SetData(std::move(td));
      
      // 设置数据类型(如果需要)
      // tensor.SetDataType(ge::DT_FLOAT);
      
    • 方法2: 使用构造函数直接创建
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      // 从 shape、format 和 dtype 构造
      gert::StorageShape shape = {{batch_size, channels, height, width}, {4}};
      gert::StorageFormat format = {ge::FORMAT_ND, ge::FORMAT_ND, {}};
      gert::Tensor tensor(shape, format, ge::DT_FLOAT);
      
      // 然后分配内存
      void* host_buf = nullptr;
      aclrtMallocHost(&host_buf, tensor.GetSize());
      gert::TensorData td(host_buf, nullptr, tensor.GetSize(), gert::kOnHost);
      tensor.SetData(std::move(td));
      
    • 方法3: 构造Device Tensor
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      // 分配Device内存
      void* dev = nullptr;
      aclError ret = aclrtMalloc(&dev, bytes, ACL_MEM_MALLOC_NORMAL_ONLY);
      if (ret != ACL_ERROR_NONE) {
          // 处理错误
      }
      
      // 构造 Device Tensor
      gert::TensorData td(dev, nullptr, bytes, gert::kOnDeviceHbm);
      gert::Tensor device_tensor;
      device_tensor.SetData(std::move(td));
      
  • 释放gert::Tensor内存
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    // 释放Host Tensor内存
    void FreeHostTensor(gert::Tensor &tensor) {
        if (tensor.GetAddr() != nullptr) {
            aclrtFreeHost(tensor.GetAddr());
        }
    }
    
    // 释放Device Tensor内存
    void FreeDeviceTensor(gert::Tensor &tensor) {
        if (tensor.GetAddr() != nullptr) {
            aclrtFree(tensor.GetAddr());
        }
    }
    
    // 批量释放
    void FreeTensorVector(std::vector<gert::Tensor> &tensors, bool is_device) {
        for (auto &t : tensors) {
            if (t.GetAddr() != nullptr) {
                if (is_device) {
                    aclrtFree(t.GetAddr());
                } else {
                    aclrtFreeHost(t.GetAddr());
                }
            }
        }
    }
    

aclrtMallocHost、aclrtMalloc、aclrtFreeHost、aclrtFree等acl接口详细说明请参见应用开发指南 (C&C++)

编译和运行接口变化

  • CompileGraph/LoadGraph不再必需

    在GeSession中,RunGraphRunGraphAsyncRunGraphWithStreamAsync三个执行接口会自动检查图是否已编译和加载。如果未编译,会先自动编译;如果未加载,会先自动加载。

    // GeSession的自动处理机制
    GeSession session(options);
    session.AddGraph(graph_id, graph);
    
    // 直接执行,无需手动CompileGraph和LoadGraph
    session.RunGraph(graph_id, inputs, outputs);  // 自动编译和加载
  • 执行模式互斥

    GeSession的三种执行模式RunGraphRunGraphAsyncRunGraphWithStreamAsync是互斥的,不能混用。一旦使用了某种执行模式,该图就必须继续使用同一种模式。

编译配置变化

Makefile或CMakeLists.txt需要更新:

Session接口

GeSession接口

# 旧配置
target_link_libraries(your_app libge_runner.so)
# 新配置
target_link_libraries(your_app libge_runner_v2.so)