Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
Dive-into-DL-PyTorch
提交
7411ca00
D
Dive-into-DL-PyTorch
项目概览
OpenDocCN
/
Dive-into-DL-PyTorch
通知
9
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Dive-into-DL-PyTorch
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
7411ca00
编写于
4月 30, 2019
作者:
S
ShusenTang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add 8.1
上级
aab87e89
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
209 addition
and
0 deletion
+209
-0
code/chapter08_computational-performance/8.1_hybridize.ipynb
code/chapter08_computational-performance/8.1_hybridize.ipynb
+122
-0
docs/chapter08_computational-performance/8.1_hybridize.md
docs/chapter08_computational-performance/8.1_hybridize.md
+87
-0
未找到文件。
code/chapter08_computational-performance/8.1_hybridize.ipynb
0 → 100644
浏览文件 @
7411ca00
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 8.1 命令式和符号式混合编程"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"10"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def add(a, b):\n",
" return a + b\n",
"\n",
"def fancy_func(a, b, c, d):\n",
" e = add(a, b)\n",
" f = add(c, d)\n",
" g = add(e, f)\n",
" return g\n",
"\n",
"fancy_func(1, 2, 3, 4)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"def add(a, b):\n",
" return a + b\n",
"\n",
"def fancy_func(a, b, c, d):\n",
" e = add(a, b)\n",
" f = add(c, d)\n",
" g = add(e, f)\n",
" return g\n",
"\n",
"print(fancy_func(1, 2, 3, 4))\n",
"\n",
"10\n"
]
}
],
"source": [
"def add_str():\n",
" return '''\n",
"def add(a, b):\n",
" return a + b\n",
"'''\n",
"\n",
"def fancy_func_str():\n",
" return '''\n",
"def fancy_func(a, b, c, d):\n",
" e = add(a, b)\n",
" f = add(c, d)\n",
" g = add(e, f)\n",
" return g\n",
"'''\n",
"\n",
"def evoke_str():\n",
" return add_str() + fancy_func_str() + '''\n",
"print(fancy_func(1, 2, 3, 4))\n",
"'''\n",
"\n",
"prog = evoke_str()\n",
"print(prog)\n",
"y = compile(prog, '', 'exec')\n",
"exec(y)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [default]",
"language": "python",
"name": "python3"
},
"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.6.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
docs/chapter08_computational-performance/8.1_hybridize.md
0 → 100644
浏览文件 @
7411ca00
# 8.1 命令式和符号式混合编程
本书到目前为止一直都在使用命令式编程,它使用编程语句改变程序状态。考虑下面这段简单的命令式程序。
```
python
def
add
(
a
,
b
):
return
a
+
b
def
fancy_func
(
a
,
b
,
c
,
d
):
e
=
add
(
a
,
b
)
f
=
add
(
c
,
d
)
g
=
add
(
e
,
f
)
return
g
fancy_func
(
1
,
2
,
3
,
4
)
# 10
```
和我们预期的一样,在运行语句
`e = add(a, b)`
时,Python会做加法运算并将结果存储在变量
`e`
中,从而令程序的状态发生改变。类似地,后面的两条语句
`f = add(c, d)`
和
`g = add(e, f)`
会依次做加法运算并存储变量。
虽然使用命令式编程很方便,但它的运行可能很慢。一方面,即使
`fancy_func`
函数中的
`add`
是被重复调用的函数,Python也会逐一执行这3条函数调用语句。另一方面,我们需要保存变量
`e`
和
`f`
的值直到
`fancy_func`
中所有语句执行结束。这是因为在执行
`e = add(a, b)`
和
`f = add(c, d)`
这2条语句之后我们并不知道变量
`e`
和
`f`
是否会被程序的其他部分使用。
与命令式编程不同,符号式编程通常在计算流程完全定义好后才被执行。多个深度学习框架,如
**Theano和TensorFlow,都使用了符号式编程**
。通常,符号式编程的程序需要下面3个步骤:
1.
定义计算流程;
2.
把计算流程编译成可执行的程序;
3.
给定输入,调用编译好的程序执行。
下面我们用符号式编程重新实现本节开头给出的命令式编程代码。
```
python
def
add_str
():
return
'''
def add(a, b):
return a + b
'''
def
fancy_func_str
():
return
'''
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
'''
def
evoke_str
():
return
add_str
()
+
fancy_func_str
()
+
'''
print(fancy_func(1, 2, 3, 4))
'''
prog
=
evoke_str
()
print
(
prog
)
y
=
compile
(
prog
,
''
,
'exec'
)
exec
(
y
)
```
输出:
```
def add(a, b):
return a + b
def fancy_func(a, b, c, d):
e = add(a, b)
f = add(c, d)
g = add(e, f)
return g
print(fancy_func(1, 2, 3, 4))
10
```
以上定义的3个函数都仅以字符串的形式返回计算流程。最后,我们通过
`compile`
函数编译完整的计算流程并运行。由于在编译时系统能够完整地获取整个程序,因此有更多空间优化计算。例如,编译的时候可以将程序改写成
`print((1 + 2) + (3 + 4))`
,甚至直接改写成
`print(10)`
。这样不仅减少了函数调用,还节省了内存。
对比这两种编程方式,我们可以看到以下两点。
*
命令式编程更方便。当我们在Python里使用命令式编程时,大部分代码编写起来都很直观。同时,命令式编程更容易调试。这是因为我们可以很方便地获取并打印所有的中间变量值,或者使用Python的调试工具。
*
符号式编程更高效并更容易移植。一方面,在编译的时候系统容易做更多优化;另一方面,符号式编程可以将程序变成一个与Python无关的格式,从而可以使程序在非Python环境下运行,以避开Python解释器的性能问题。
## 8.1.1 混合式编程取两者之长
大部分深度学习框架在命令式编程和符号式编程之间二选一。例如,
**Theano和受其启发的后来者TensorFlow使用了符号式编程,Chainer和它的追随者PyTorch使用了命令式编程,而Gluon则采用了混合式编程的方式**
。
......
> 由于PyTorch仅仅采用了命令式编程,所以跳过本节剩余部分,感兴趣的可以去看[原文](https://zh.d2l.ai/chapter_computational-performance/hybridize.html)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录