文档反馈

问题文档片段

问题文档片段包含公式时,显示为空格。

提交类型
issue

有点复杂...

找人问问吧。

PR

小问题,全程线上修改...

一键搞定!

请选择提交类型

问题类型
规范和低错类

- 规范和低错类:

- 错别字或拼写错误,标点符号使用错误、公式错误或显示异常。

- 链接错误、空单元格、格式错误。

- 英文中包含中文字符。

- 界面和描述不一致,但不影响操作。

- 表述不通顺,但不影响理解。

- 版本号不匹配:如软件包名称、界面版本号。

易用性

- 易用性:

- 关键步骤错误或缺失,无法指导用户完成任务。

- 缺少主要功能描述、关键词解释、必要前提条件、注意事项等。

- 描述内容存在歧义指代不明、上下文矛盾。

- 逻辑不清晰,该分类、分项、分步骤的没有给出。

正确性

- 正确性:

- 技术原理、功能、支持平台、参数类型、异常报错等描述和软件实现不一致。

- 原理图、架构图等存在错误。

- 命令、命令参数等错误。

- 代码片段错误。

- 命令无法完成对应功能。

- 界面错误,无法指导操作。

- 代码样例运行报错、运行结果不符。

风险提示

- 风险提示:

- 对重要数据或系统存在风险的操作,缺少安全提示。

内容合规

- 内容合规:

- 违反法律法规,涉及政治、领土主权等敏感词。

- 内容侵权。

请选择问题类型

问题描述

点击输入详细问题描述,以帮助我们快速定位问题。

ms_function动静结合

Ascend GPU CPU 模型运行

在线运行下载Notebook下载样例代码查看源文件

概述

ms_function的作用是在PyNative模式下提升执行性能。在MindSpore框架中,PyNative模式(即动态图模式)下,用户可以使用完整的Python语法,更加简单方便地使用MindSpore进行网络调优。与此同时,PyNative模式也会导致一部分性能的损失。

ms_function支持在PyNative模式下,让被ms_function修饰的程序以静态图的方式来运行。ms_function会将修饰的程序通过静态编译的方式来生成可执行图,整体下发执行,从而提升该修饰部分的执行性能。

本文档主要介绍ms_function的使用方法和工作原理,以便您可以更有效地使用ms_function功能。

修饰独立函数

使用ms_function装饰器时,可以对独立定义的函数进行修饰。

[1]:
# pylint: disable=W0235,W0612
import numpy as np
import mindspore.ops as ops
from mindspore import context, Tensor, ms_function

@ms_function
def add_func(x, y):
    return ops.add(x, y)


context.set_context(mode=context.PYNATIVE_MODE)
x = Tensor(np.ones([3, 3], dtype=np.float32))
y = Tensor(np.ones([3, 3], dtype=np.float32))
out = add_func(x, y)
print(out)
[[2. 2. 2.]
 [2. 2. 2.]
 [2. 2. 2.]]

修饰Cell的成员函数

使用ms_function装饰器时,可以对Cell的成员函数进行修饰。

[2]:
import numpy as np
import mindspore.nn as nn
import mindspore.ops as ops
from mindspore import context, Tensor, ms_function

class Add(nn.Cell):
    def __init__(self):
        super(Add, self).__init__()

    @ms_function
    def construct(self, x, y):
        out = x * y
        return out


context.set_context(mode=context.PYNATIVE_MODE)
x = Tensor(np.ones([3, 3], dtype=np.float32))
y = Tensor(np.ones([3, 3], dtype=np.float32))
grad_ops = ops.GradOperation(get_all=True)
net = Add()
grad_out = grad_ops(net)(x, y)
print(grad_out)
(Tensor(shape=[3, 3], dtype=Float32, value=
[[1.00000000e+000, 1.00000000e+000, 1.00000000e+000],
 [1.00000000e+000, 1.00000000e+000, 1.00000000e+000],
 [1.00000000e+000, 1.00000000e+000, 1.00000000e+000]]), Tensor(shape=[3, 3], dtype=Float32, value=
[[1.00000000e+000, 1.00000000e+000, 1.00000000e+000],
 [1.00000000e+000, 1.00000000e+000, 1.00000000e+000],
 [1.00000000e+000, 1.00000000e+000, 1.00000000e+000]]))

实现原理

本小节将介绍ms_function的实现原理,当你深入了解了ms_function的工作原理时,你将会更高效地使用ms_function。

以一个简单的动静结合的用例来说明,如下:

[3]:
import numpy as np
import mindspore.nn as nn
from mindspore import context, Tensor, ms_function

class Add(nn.Cell):
    def __init__(self):
        super(Add, self).__init__()

    def construct(self, x):
        x = x + x
        x = x + x
        return x


class Mul(nn.Cell):
    def __init__(self):
        super(Mul, self).__init__()

    @ms_function
    def construct(self, x):
        x = x * x
        x = x * x
        return x


class Test(nn.Cell):
    def __init__(self):
        super(Test, self).__init__()
        self.add = Add()
        self.mul = Mul()

    def construct(self, x):
        x = self.add(x)
        x = self.mul(x)
        x = self.add(x)
        return x


context.set_context(mode=context.PYNATIVE_MODE)
x = Tensor(np.ones([3, 3], dtype=np.float32))
net = Test()
out = net(x)
print(out)
[[1024. 1024. 1024.]
 [1024. 1024. 1024.]
 [1024. 1024. 1024.]]

该用例按照执行序,编译的方式如下图所示:

image

被ms_function修饰的函数将会按照静态图的方式进行编译和执行。如果网络涉及到反向求导,被ms_function修饰的部分也将以整图的形式来生成反向图,并与前后单个算子的反向图连成整体的反向图,下发执行。 其中,缓存的策略与静态图的缓存策略一致,相同的函数对象在输入Shape和Type信息一致时,编译的图结构将会被缓存。

使用须知

在使用ms_function来修饰函数,加速执行效率时,请注意以下几点:

  1. ms_function修饰的函数须在静态图编译支持的语法范围内,包括但不限于数据类型等。

  2. ms_function修饰的函数所支持的控制流语法,与静态图保持一致。其中,仅对固定循环次数或者分支条件的控制流结构具有加速效果。

  3. 在PyNative模式下使用ms_function功能时,非ms_function修饰的部分支持断点调试;被ms_function修饰的部分由于是以静态图的方式编译,不支持断点调试。

  4. 由于ms_function修饰的函数将按照静态图的方式编译执行,因此ms_function不支持修饰的函数中含有Hook算子,以及不支持修饰自定义Bprop函数等。

  5. ms_function修饰的函数会受到静态图函数副作用的影响。

函数副作用指:当调用函数时,除了函数返回值之外,还对主调用函数产生的附加影响。例如修改全局变量(函数外的变量),修改函数的参数等。

场景1:

[4]:
import numpy as np
from mindspore import context, Tensor, ms_function

value = 5

@ms_function
def func(x, y):
    out = x + y
    value = 1
    return out

context.set_context(mode=context.PYNATIVE_MODE)
x = Tensor(np.ones([3, 3], dtype=np.float32))
y = Tensor(np.ones([3, 3], dtype=np.float32))
func(x, y)
print(value)
5

该场景下,value是全局变量且在func函数中被修改。此时,如果用ms_function修饰func函数,全局变量value的值将不会被修改。原因是静态图编译时,会优化掉与返回值无关的语句。

场景2:

[5]:
import numpy as np
import mindspore.nn as nn
from mindspore import context, Tensor, ms_function

class Func(nn.Cell):
    def __init__(self):
        super(Func, self).__init__()
        self.value = 5

    @ms_function
    def construct(self, x):
        out = self.value + x
        return out

context.set_context(mode=context.PYNATIVE_MODE)
x = Tensor(np.ones([3, 3], dtype=np.float32))
func = Func()
out = func(x)
func.value = 1
out = func(x)
print(out)
[[6. 6. 6.]
 [6. 6. 6.]
 [6. 6. 6.]]

该场景下,valueFunc对象的参数,此时如果用ms_function修饰Func对象的construct成员函数。执行Func时将会以静态图的方式编译执行。由于静态图会缓存编译结果,第二次调用Func时,对value的修改将不会生效。