From 4b807674509ea24b282cdf499d93e74e82c93244 Mon Sep 17 00:00:00 2001
From: hxzd5568 <40557101+hxzd5568@users.noreply.github.com>
Date: Sun, 7 Aug 2022 00:09:33 +0800
Subject: [PATCH 1/5] add 20220807_api_design_for_flip.md
---
.../CINN/APIs/20220807_api_design_for_flip.md | 153 ++++++++++++++++++
1 file changed, 153 insertions(+)
create mode 100644 rfcs/CINN/APIs/20220807_api_design_for_flip.md
diff --git a/rfcs/CINN/APIs/20220807_api_design_for_flip.md b/rfcs/CINN/APIs/20220807_api_design_for_flip.md
new file mode 100644
index 000000000..1000509c8
--- /dev/null
+++ b/rfcs/CINN/APIs/20220807_api_design_for_flip.md
@@ -0,0 +1,153 @@
+# CINN flip 设计文档
+
+| API名称 | 新增API名称 |
+| ------------------------------------------------------------ | ------------------------------------------------------------ |
+| 提交作者 | 小小夏 |
+| 提交时间 | 2022-08-06 |
+| 版本号 | V1.0 |
+| 依赖飞桨版本 | develop |
+| 文件名 | 20220807_api_design_for_flip.md |
+
+
+# 一、概述
+
+## 1、相关背景
+
+flip是众多神经网络编译器中基础的算子,属于injection级别,它将输入的指定维度上进行元素翻转。
+
+## 2、功能目标
+
+实现flip功能
+
+## 3、意义
+
+为神经网络编译器 CINN 增加基础算子flip
+
+# 二、飞桨现状
+
+CINN框架目前不支持此功能,暂时没有比较好的 API 替代,因此有必要实现flip算子
+
+
+# 三、业内方案调研
+
+
+
+tensorflow中调用了numpy的flip实现:
+
+```python
+@array_function_dispatch(_flip_dispatcher)
+def flip(m, axis=None):
+ """
+ Reverse the order of elements in an array along the given axis.
+ The shape of the array is preserved, but the elements are reordered.
+ .. versionadded:: 1.12.0
+ Parameters
+ ----------
+ m : array_like
+ Input array.
+ axis : None or int or tuple of ints, optional
+ Axis or axes along which to flip over. The default,
+ axis=None, will flip over all of the axes of the input array.
+ If axis is negative it counts from the last to the first axis.
+ If axis is a tuple of ints, flipping is performed on all of the axes
+ specified in the tuple.
+ .. versionchanged:: 1.15.0
+ None and tuples of axes are supported
+ Returns
+ -------
+ out : array_like
+ A view of `m` with the entries of axis reversed. Since a view is
+ returned, this operation is done in constant time.
+ See Also
+ --------
+ flipud : Flip an array vertically (axis=0).
+ fliplr : Flip an array horizontally (axis=1).
+ Notes
+ -----
+ flip(m, 0) is equivalent to flipud(m).
+ flip(m, 1) is equivalent to fliplr(m).
+ flip(m, n) corresponds to ``m[...,::-1,...]`` with ``::-1`` at position n.
+ flip(m) corresponds to ``m[::-1,::-1,...,::-1]`` with ``::-1`` at all
+ positions.
+ flip(m, (0, 1)) corresponds to ``m[::-1,::-1,...]`` with ``::-1`` at
+ position 0 and position 1.
+ """
+ if not hasattr(m, 'ndim'):
+ m = asarray(m)
+ if axis is None:
+ indexer = (np.s_[::-1],) * m.ndim
+ else:
+ axis = _nx.normalize_axis_tuple(axis, m.ndim)
+ indexer = [np.s_[:]] * m.ndim
+ for ax in axis:
+ indexer[ax] = np.s_[::-1]
+ indexer = tuple(indexer)
+ return m[indexer]
+```
+
+该方案特点是实际返回了一个原始array的视图,不需要新的空间,时间复杂度低。
+
+pytorch则返回了一个新的tensor:
+
+```
+torch.flip(input, dims) → Tensor
+Reverse the order of a n-D tensor along given axis in dims.
+
+NOTE
+
+torch.flip makes a copy of input’s data. This is different from NumPy’s np.flip, which returns a view in constant time. Since copying a tensor’s data is more work than viewing that data, torch.flip is expected to be slower than np.flip.
+}
+```
+
+# 四、对比分析
+
+在业界,pytorch和numpy的实现基本相同,但前者产生一个数据拷贝,而后者仅仅返回一个视图。
+
+# 五、设计思路与实现方案
+
+可以实现对所有维度,单个维度,多个指定维度的数据转化,并返回一个新的拷贝。
+
+## 命名与参数设计
+
+- A:输入张量
+- dim:需要翻转的维度(可以为None,int ,tuple)缺省时表示翻转所有维度
+
+## 底层OP设计
+
+1. 在 `cinn/hlir/op/contrib/flip.h` 里声明`flip`算子。
+2. 在 `cinn/hlir/op/contrib/flip.cc` 里实现`flip`算子和 `strategy`。
+
+## API实现方案
+
+实现目标为对于张量 A = (M, N, K),flip( A, a_max, a_min) 结果尺寸为 A = (M, N, K) 不变,但其中的数值发生变化,任一元素的值都在[ a_min, a_max ]的区间范围内
+
+1. 在 `cinn/frontend/net_build.h` 里声明 `NetBuilder::flip`。
+2. 在 `cinn/frontend/net_build.cc` 里实现 `NetBuilder::flip`。
+3. 在 `cinn/pybind/frontend` 对 Python 类 `NetBuilder` 添加 `flip` 接口,并绑定到 `NetBuilder::flip`。
+4. 上层 `load_paddle_model` 调用提交到 `cinn/frontend/paddle_model_to_program.h` 和 `.cc` 文件下。
+
+通过使用 Builder 类的方法调用 flip。
+
+```python
+builder = CinnBuilder("test_basic")
+a = builder.create_input(Float(32), (32, 16, 16), "A")
+b = builder.flip(a,1)
+b = builder.flip(a,(0,1))
+b = builder.flip(a)
+```
+
+# 六、测试和验收的考量
+
+1. 提供基础的 demo 文件。
+
+2. 在`cinn/hlir/op/contrib/flip_test.cc`中添加对底层OP进行测试的代码,在`cinn/frontend/net_builder_test.cc`中添加对前端的测试。
+3. 提交 API 使用方法到相应的文档中。
+
+# 七、可行性分析和排期规划
+
+- 可行性分析:非常可行
+- 排期规划:底层OP设计已完成,API、测试和文档部分预计15天内完成
+
+# 八、影响面
+
+对其他模块无影响。
From 4054683d97b326ff7acb23ba52a69e6ea92e5aad Mon Sep 17 00:00:00 2001
From: hxzd5568 <40557101+hxzd5568@users.noreply.github.com>
Date: Sun, 7 Aug 2022 00:19:57 +0800
Subject: [PATCH 2/5] Update 20220807_api_design_for_flip.md
---
rfcs/CINN/APIs/20220807_api_design_for_flip.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rfcs/CINN/APIs/20220807_api_design_for_flip.md b/rfcs/CINN/APIs/20220807_api_design_for_flip.md
index 1000509c8..483ca65a3 100644
--- a/rfcs/CINN/APIs/20220807_api_design_for_flip.md
+++ b/rfcs/CINN/APIs/20220807_api_design_for_flip.md
@@ -119,7 +119,7 @@ torch.flip makes a copy of input’s data. This is different from NumPy’s np.f
## API实现方案
-实现目标为对于张量 A = (M, N, K),flip( A, a_max, a_min) 结果尺寸为 A = (M, N, K) 不变,但其中的数值发生变化,任一元素的值都在[ a_min, a_max ]的区间范围内
+实现目标为对于张量 A = (M, N, K),flip( A, dim) 结果尺寸为 A = (M, N, K) 不变,但其中的数值顺序发生变化,dim维度上的数据发生翻转。
1. 在 `cinn/frontend/net_build.h` 里声明 `NetBuilder::flip`。
2. 在 `cinn/frontend/net_build.cc` 里实现 `NetBuilder::flip`。
From c9c355aae19fd0e911109037a35460243733f612 Mon Sep 17 00:00:00 2001
From: hxzd5568 <40557101+hxzd5568@users.noreply.github.com>
Date: Thu, 11 Aug 2022 14:07:10 +0800
Subject: [PATCH 3/5] Update 20220807_api_design_for_flip.md
---
.../CINN/APIs/20220807_api_design_for_flip.md | 38 +++++++++++++++++--
1 file changed, 35 insertions(+), 3 deletions(-)
diff --git a/rfcs/CINN/APIs/20220807_api_design_for_flip.md b/rfcs/CINN/APIs/20220807_api_design_for_flip.md
index 483ca65a3..2c8bbe693 100644
--- a/rfcs/CINN/APIs/20220807_api_design_for_flip.md
+++ b/rfcs/CINN/APIs/20220807_api_design_for_flip.md
@@ -1,6 +1,6 @@
# CINN flip 设计文档
-| API名称 | 新增API名称 |
+| API名称 | flip |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| 提交作者 | 小小夏 |
| 提交时间 | 2022-08-06 |
@@ -13,11 +13,43 @@
## 1、相关背景
-flip是众多神经网络编译器中基础的算子,属于injection级别,它将输入的指定维度上进行元素翻转。
+flip是众多神经网络编译器中基础的算子,属于injective类型的算子,它将输入的指定维度上进行元素翻转。(Injective operator, can always injectively map output axis to a single input axis. All injective operator can still be safely fused to injective and reduction.)
## 2、功能目标
-实现flip功能
+实现flip功能,在指定维度翻转元素顺序。Reverse the order of elements in an array along the given axis.
+可以实现对所有维度,单个维度,多个指定维度的数据转化,并返回一个新的拷贝。输入需要处理的张量以及需要翻转的维度(可以为None,int ,tuple)缺省时表示翻转所有维度。
+```
+example
+
+ A = [[[0, 1],
+ [2, 3]],
+ [[4, 5],
+ [6, 7]]]
+
+ flip(A, 0)
+ >>>[[[4, 5],
+ [6, 7]],
+ [[0, 1],
+ [2, 3]]]
+ flip(A, 1)
+ >>>[[[2, 3],
+ [0, 1]],
+ [[6, 7],
+ [4, 5]]]
+ flip(A)
+ >>>[[[7, 6],
+ [5, 4]],
+ [[3, 2],
+ [1, 0]]]
+ flip(A, (0, 2))
+ >>>[[[5, 4],
+ [7, 6]],
+ [[1, 0],
+ [3, 2]]]
+
+
+```
## 3、意义
From 5a90ddba1c966c79a80a7b01c2b34ee594ac9dbb Mon Sep 17 00:00:00 2001
From: hxzd5568 <40557101+hxzd5568@users.noreply.github.com>
Date: Thu, 11 Aug 2022 14:09:32 +0800
Subject: [PATCH 4/5] Update 20220807_api_design_for_flip.md
---
rfcs/CINN/APIs/20220807_api_design_for_flip.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/rfcs/CINN/APIs/20220807_api_design_for_flip.md b/rfcs/CINN/APIs/20220807_api_design_for_flip.md
index 2c8bbe693..322f58df4 100644
--- a/rfcs/CINN/APIs/20220807_api_design_for_flip.md
+++ b/rfcs/CINN/APIs/20220807_api_design_for_flip.md
@@ -17,7 +17,8 @@ flip是众多神经网络编译器中基础的算子,属于injective类型的
## 2、功能目标
-实现flip功能,在指定维度翻转元素顺序。Reverse the order of elements in an array along the given axis.
+flip(tensor,dim):Reverse the order of elements in an array along the given axis.
+实现flip功能,在指定维度翻转元素顺序。
可以实现对所有维度,单个维度,多个指定维度的数据转化,并返回一个新的拷贝。输入需要处理的张量以及需要翻转的维度(可以为None,int ,tuple)缺省时表示翻转所有维度。
```
example
From a73bd72adc91a32745a6c4adc887401070686f8a Mon Sep 17 00:00:00 2001
From: hxzd5568 <40557101+hxzd5568@users.noreply.github.com>
Date: Tue, 16 Aug 2022 19:16:06 +0800
Subject: [PATCH 5/5] Update 20220807_api_design_for_flip.md
---
.../CINN/APIs/20220807_api_design_for_flip.md | 55 +++++++++----------
1 file changed, 27 insertions(+), 28 deletions(-)
diff --git a/rfcs/CINN/APIs/20220807_api_design_for_flip.md b/rfcs/CINN/APIs/20220807_api_design_for_flip.md
index 322f58df4..09925f5d0 100644
--- a/rfcs/CINN/APIs/20220807_api_design_for_flip.md
+++ b/rfcs/CINN/APIs/20220807_api_design_for_flip.md
@@ -13,40 +13,40 @@
## 1、相关背景
-flip是众多神经网络编译器中基础的算子,属于injective类型的算子,它将输入的指定维度上进行元素翻转。(Injective operator, can always injectively map output axis to a single input axis. All injective operator can still be safely fused to injective and reduction.)
+flip是众多神经网络编译器中基础的算子,该算子代表的数学函数属于injection类型。它将输入的指定维度上进行元素翻转。(Injective operator, can always injectively map output axis to a single input axis. All injective operator can still be safely fused to injective and reduction.)
## 2、功能目标
-flip(tensor,dim):Reverse the order of elements in an array along the given axis.
+flip(tensor, dim):Reverse the order of elements in an array along the given axis.
实现flip功能,在指定维度翻转元素顺序。
-可以实现对所有维度,单个维度,多个指定维度的数据转化,并返回一个新的拷贝。输入需要处理的张量以及需要翻转的维度(可以为None,int ,tuple)缺省时表示翻转所有维度。
+可以实现对所有维度,单个维度,多个指定维度的数据转化,并返回一个新的拷贝。输入需要处理的张量以及需要翻转的维度(可以为None, int, tuple)缺省时表示翻转所有维度。
```
example
- A = [[[0, 1],
- [2, 3]],
- [[4, 5],
+ A = [[[0, 1],
+ [2, 3]],
+ [[4, 5],
[6, 7]]]
flip(A, 0)
- >>>[[[4, 5],
- [6, 7]],
- [[0, 1],
+ >>>[[[4, 5],
+ [6, 7]],
+ [[0, 1],
[2, 3]]]
flip(A, 1)
- >>>[[[2, 3],
- [0, 1]],
- [[6, 7],
+ >>>[[[2, 3],
+ [0, 1]],
+ [[6, 7],
[4, 5]]]
flip(A)
- >>>[[[7, 6],
- [5, 4]],
- [[3, 2],
+ >>>[[[7, 6],
+ [5, 4]],
+ [[3, 2],
[1, 0]]]
flip(A, (0, 2))
- >>>[[[5, 4],
- [7, 6]],
- [[1, 0],
+ >>>[[[5, 4],
+ [7, 6]],
+ [[1, 0],
[3, 2]]]
@@ -79,7 +79,7 @@ def flip(m, axis=None):
m : array_like
Input array.
axis : None or int or tuple of ints, optional
- Axis or axes along which to flip over. The default,
+ Axis or axes along which to flip over. The default,
axis=None, will flip over all of the axes of the input array.
If axis is negative it counts from the last to the first axis.
If axis is a tuple of ints, flipping is performed on all of the axes
@@ -99,16 +99,16 @@ def flip(m, axis=None):
-----
flip(m, 0) is equivalent to flipud(m).
flip(m, 1) is equivalent to fliplr(m).
- flip(m, n) corresponds to ``m[...,::-1,...]`` with ``::-1`` at position n.
- flip(m) corresponds to ``m[::-1,::-1,...,::-1]`` with ``::-1`` at all
+ flip(m, n) corresponds to ``m[..., ::-1, ...]`` with ``::-1`` at position n.
+ flip(m) corresponds to ``m[::-1, ::-1, ..., ::-1]`` with ``::-1`` at all
positions.
- flip(m, (0, 1)) corresponds to ``m[::-1,::-1,...]`` with ``::-1`` at
+ flip(m, (0, 1)) corresponds to ``m[::-1, ::-1, ...]`` with ``::-1`` at
position 0 and position 1.
"""
if not hasattr(m, 'ndim'):
m = asarray(m)
if axis is None:
- indexer = (np.s_[::-1],) * m.ndim
+ indexer = (np.s_[::-1], ) * m.ndim
else:
axis = _nx.normalize_axis_tuple(axis, m.ndim)
indexer = [np.s_[:]] * m.ndim
@@ -128,7 +128,7 @@ Reverse the order of a n-D tensor along given axis in dims.
NOTE
-torch.flip makes a copy of input’s data. This is different from NumPy’s np.flip, which returns a view in constant time. Since copying a tensor’s data is more work than viewing that data, torch.flip is expected to be slower than np.flip.
+torch.flip makes a copy of input's data. This is different from NumPy's np.flip, which returns a view in constant time. Since copying a tensor's data is more work than viewing that data, torch.flip is expected to be slower than np.flip.
}
```
@@ -143,7 +143,7 @@ torch.flip makes a copy of input’s data. This is different from NumPy’s np.f
## 命名与参数设计
- A:输入张量
-- dim:需要翻转的维度(可以为None,int ,tuple)缺省时表示翻转所有维度
+- dim:需要翻转的维度(可以为None, int, tuple)缺省时表示翻转所有维度
## 底层OP设计
@@ -164,15 +164,14 @@ torch.flip makes a copy of input’s data. This is different from NumPy’s np.f
```python
builder = CinnBuilder("test_basic")
a = builder.create_input(Float(32), (32, 16, 16), "A")
-b = builder.flip(a,1)
-b = builder.flip(a,(0,1))
+b = builder.flip(a, 1)
+b = builder.flip(a, (0, 1))
b = builder.flip(a)
```
# 六、测试和验收的考量
1. 提供基础的 demo 文件。
-
2. 在`cinn/hlir/op/contrib/flip_test.cc`中添加对底层OP进行测试的代码,在`cinn/frontend/net_builder_test.cc`中添加对前端的测试。
3. 提交 API 使用方法到相应的文档中。