MindSpore 的 Python 侧是其主要用户接口,提供了高层 API,便于快速构建和训练深度学习模型。Python 侧注重开发效率和灵活性,支持动态图(PyNative 模式)和静态图(Graph 模式)两种执行模式,适合算法工程师和数据科学家进行快速原型设计和实验。Python 的语法简洁,支持自动内存管理和动态类型,开发速度快,且提供了丰富的预定义模块和工具(如 `mindspore.nn`、`mindspore.ops`),便于快速实现模型定义、训练和推理任务。此外,Python 侧还支持数据预处理、可视化工具(如 MindSpore Insight)和模型仓库(如 MindSpore Hub),社区生态丰富且支持广泛。
MindSpore 的 C++ 侧更偏向底层,主要用于高性能计算、算子开发、硬件适配和框架扩展。C++ 侧强调性能和底层控制,适合框架开发者和硬件工程师进行深度优化和自定义算子开发。C++ 是编译型语言,执行效率高,能够直接操作硬件资源(如 GPU、NPU),适合对性能要求极高的场景,如嵌入式设备和边缘计算。C++ 侧需要手动管理内存和数据类型,开发效率较低,但提供了对计算图、算子和硬件资源的直接控制能力,适合开发高性能推理引擎和底层优化模块。C++ 侧的生态相对局限,工具链较少,但对性能优化和硬件适配的支持更强。
下面从参数保存加载过程中,简单看下Mindspore如何实现Python侧和C++侧之间的链接。
# 01
save_checkpoint整体流程
保存checkpoint过程中,有以下几个流程:
1、从nn.cell中过滤出来保存的parameter:
save_obj = _convert_save_obj_to_param_list(save_obj, integrated_save, append_dict, choice_func)2、对parameter进行一系列处理,提取参数名,shape,dtype等重要信息。处理后的结果存储在data_list的字典中。
3、将逐个parameter写入文件中。
def _write_parameter_bytes_data(name, value, f, enc_key, plain_data, crc_num=0, crc_check=False, ckpt_total_io_time=0):"""Write parameter bytes data into protobuf file."""bytes_value = value[2].get_bytes()chunk_size = 1024 * SLICE_SIZE...
这里的tensor.get_bytes()函数,用来获取tensor的bytes值。
# 02
Tensor.get_bytes函数
1、pybind11简单介绍
pybind11 是一个轻量级的 C++ 库,用于将 C++ 代码暴露给 Python,从而实现 C++ 和 Python 之间的无缝互操作。它的目标是简化 C++ 代码与 Python 的绑定过程,同时保持高性能和低开销。
MindSpore使用pybind11连接Python侧的接口和C++侧的接口,兼顾Python的简单便捷和C++的高性能。
2、具体实现
1、Python侧接口定义在mindspore/python/mindspore/common/tensor.py:tensor.py实现了大部分常用的张量操作。
def get_bytes(self):r"""Get raw data of tensor with type of bytes.Supported Platforms:``CPU`` ``GPU`` ``Ascend``Returns:Bytes of tensor.Examples:>>> import mindspore as ms>>> from mindspore import Tensor>>> x = ms.Tensor([1, 2, 3], ms.int16)>>> print(x.get_bytes())b'\x01\x00\x02\x00\x03\x00'"""return TensorPy_.get_bytes(self)
2、C++侧接口定义在mindspore/ccsrc/utils/tensor_py.cc。tenosor_py.cc文件下实现了tensor的C++侧的接口。
py::bytes TensorPybind::GetBytes(const Tensor &tensor){py::gil_scoped_acquire acquire;if (tensor.get_copy_done_flag()) {const_cast<Tensor &>(tensor).set_copy_done_flag(false);return py::bytes(static_cast<const char *>(tensor.data_c()), tensor.Size());}tensor.data_sync();return py::bytes(static_cast<const char *>(tensor.data_c()), tensor.Size());}py::bytes TensorPyImpl::GetBytes(const TensorPyPtr &tensorpy){auto tensor = tensorpy->GetTensor();return TensorPybind::GetBytes(*tensor);}
3、pybind绑定Python侧和C++侧。mindspore/ccsrc/pybind_api/tensor_py_reg.cc。
void RegTensorPyFunction(py::class_<TensorPy, std::shared_ptr<TensorPy>> *tensor_class) {...tensor_class->def("get_bytes", TensorPyImpl::GetBytes, R"mydelimiter(Get raw data of tensor with type of bytes.Returns:Bytes of tensor.Examples:>>> import mindspore as ms>>> from mindspore import Tensor>>> x = ms.Tensor([1, 2, 3], ms.int16)>>> print(x.get_bytes())b'\x01\x00\x02\x00\x03\x00')mydelimiter");...}
如果自定义实现方法的话,需要编译MindSpore源码后才能使用自定义的功能。
# 03
Tensor_.convert_bytes_to_tensor函数
同理在加载ckpt时,用到了类似实现的方法Tensor_.convert_bytes_to_tensor。读者可以自己看看源码,理解下pybind11如何连接的MindSpore的C++和Python层。
# 04
总结
在MindSpore中习惯将Python侧的tensor称为Tensor, C++侧的tensor称为Tensor_。
from mindspore.common.tensor import Tensorfrom mindspore._c_expression import TensorPy as Tensor_
总结来说,Python 侧适合快速开发和实验,而 C++ 侧适合高性能计算和底层优化,两者相辅相成,共同支撑 MindSpore 的全场景 AI 计算能力。
长按或扫描下方二维码,免费获取 Python公开课和大佬打包整理的几百G的学习资料,内容包含但不限于Python电子书、教程、项目接单、源码等等 推荐阅读
点击 阅读原文 了解更多