# oneflow 的作业函数
oneflow的作业函数是用来描述网络的。
通过`@oneflow.global_function`修饰的python函数,就是作业函数。
oneflow 作业函数的运行,其实分为以下几个步骤:
* python层面:编写作业函数,利用`@oneflow.global_function`编译、序列化,并且通知C++层次编译和优化
* 编译时层面:将运行时需要的信息,变为为执行计划(Plan)
* 运行时层面(C++实现):读取上一步骤的Plan,运行
# global function signature
我们可以通过`oneflow.global_function`来修饰得到作业函数。
作业函数里面都是占位符,没有真实的数据。
`oneflow`提供了一系列的 type,限制/告之 数据占位符的形状和性质。
## 作业函数的参数
在 `oneflow.typing` 里面,有:
* oft.Numpy:对应了 `numpy.ndarray`
* oft.ListNumpy:对应了 list of `numpy.ndarray`,和分布式有关
* oft.ListListNumpy: 对应了 list of list of `numpy.ndarray`,和分布式有关
* oft.Callback: 和异步有关
```python
def train_job(images:oft.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),
labels:oft.Numpy.Placeholder((BATCH_SIZE, ), dtype=flow.int32)) -> Tuple[oft.Numpy] :
```
在调用时,直接传递和占位符性质一致,性质一致的 `numpy.ndarray` 即可:
```python
train_job(images, labels)
```
## 作业函数的返回值
返回值,也是通过注解形式指定的。
简单而言,`Callback`就是异步方式调用;其它的方式,都是同步的方式调用。
```python
def train_job(images:oft.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),
labels:oft.Numpy.Placeholder((BATCH_SIZE, ), dtype=flow.int32)) -> oft.Numpy :
```
对应的调用:
```python
loss = train_job(images, labels)
if i % 20 == 0: print(loss.mean())
```
以上,是返回一个结果的例子。
如果想要返回多个结果,可以利用`typing.Tuple`指定注解类型。
```python
def train_job(images:oft.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),
labels:oft.Numpy.Placeholder((BATCH_SIZE, ), dtype=flow.int32)) -> Tuple[oft.Numpy, oft.Numpy] :
```
对应的调用:
```python
mytuple = train_job(images, labels)
if i % 20 == 0: print(mytuple[0].mean(), mytuple[1].mean())
```
如果作业函数不返回数据,需要显式指定:
```python
def train_job(images:oft.Numpy.Placeholder((BATCH_SIZE, 1, 28, 28), dtype=flow.float),
labels:oft.Numpy.Placeholder((BATCH_SIZE, ), dtype=flow.int32)) -> None:
```
请登录后评论~