Skip to content

metaphor between programming language and refactored Paddle #3570

Closed
@reyoung

Description

@reyoung

我认为我们的设计非常接近于函数式编程语言。原因有:

  1. Paddle重构后的基础元素是Operator,本质上就是一个没有side-effects的函数。
  2. Paddle的所有Operator都会返回一个或多个值。包括if-elsewhile
  3. Paddle的计算是延后的,惰性的。即先定义Operator。当我们要求某一个输出的时候,再去运行和这个输出有关的Operators,不处理无关的Operators。

这三点基本上一个函数式编程语言都具备,譬如lisp,haskell和scala。所以,据此关联编程语言,特别是函数式编程语言,到Paddle重构后的概念如下:

所有的Op都返回Expression

命令式编程语言和函数式编程语言的一个重要区别就是函数式编程语言的每一行都是Expression,而命令式编程语言的每一行都是Statement。Expression与Statement的区别是Expression永远是有返回值的。

函数式风格特别适宜描写RNN,IfElseOp等操作。例如如下 if-else的Scala代码

var hidden:Int = 39
hidden = if (hidden % 2 == 0) {
	var tmp = hidden / 2
	tmp = tmp * tmp
	tmp
} else {
	hidden + 1
}

与 for循环代码(rnn)

var x1 = Array(1, 2, 3)
var x2 = Array(4, 5, 6)

var rnn = for( all <- x1 zip x2) yield {
	all._1 * all._2
}

均和我们的If-Else与RNNOp的逻辑一致。即,If-Else两个分支分别处理数据,但是在最终二者一起返回一个值。RNNOp也是将最后的输出组合成一个值返回。

StepScope和IfElse Scope

如同上述的scala代码所示,RNN的每一个时间步和IfElse的每一个分支都有一个子Scope,这些Scope继承自外部的Scope。换成Scala代码的逻辑是,每一个 {} 中都是新的变量作用域。但是内部作用域可以访问外部的变量。

但值得注意的是,NetOp并不一定和编程语言里的Block一一对应。NetOp的含义是将常见的多个操作放到一起。所以更像使用宏定义的函数。譬如。

// Macro For FC
#define FC(input)\
  sigmoid(rowwise_add(mul_op(input, 'W'), 'b'))

而是否产生新的Block,只取决于是否新建了Scope。RNN和IfElse都会默认新建Scope,正如for循环和IfElse操作都要接大括号一样。但是其他的大括号怎么加,并不是我们这个框架应该决定的。

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions