diff --git a/rfcs/APIs/20020329_api_design_for_sparse_subtract.md b/rfcs/APIs/20020329_api_design_for_sparse_subtract.md index 1c4f8b03a..a7ba18810 100644 --- a/rfcs/APIs/20020329_api_design_for_sparse_subtract.md +++ b/rfcs/APIs/20020329_api_design_for_sparse_subtract.md @@ -1,12 +1,12 @@ # paddle.sparse.subtract 设计文档 -|API名称 | paddle.sparse.subtract | - |----------------------------------------|-----------------------------------------------------------| -|提交作者 | PeachML | -|提交时间 | 2022-03-29 | -|版本号 | V1.0 | -|依赖飞桨版本 | develop | -|文件名 | 20220329_api_design_for_sparse_subtract.md
| +| API名称 | paddle.sparse.subtract | +|----------------------------------------------------------|------------------------------------------------| +| 提交作者 | PeachML | +| 提交时间 | 2022-03-29 | +| 版本号 | V1.0 | +| 依赖飞桨版本 | develop | +| 文件名 | 20220329_api_design_for_sparse_subtract.md
| # 一、概述 @@ -141,7 +141,7 @@ Scipy中有csr类型的稀疏矩阵,可以支持相减操作,通过`binary_o # 四、对比分析 -torch设计结构复杂,为了适配paddle phi库的设计模式,故采用scipy的实现方式 +torch设计结构复杂,为了适配paddle phi库的设计模式,故参考scipy的实现方式 # 五、方案设计 @@ -150,55 +150,85 @@ torch设计结构复杂,为了适配paddle phi库的设计模式,故采用sc 在paddle/phi/kernels/sparse/目录下, kernel设计为 ``` -void SubtractCsrKernel(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y, - SparseCsrTensor* out); +void ElementWiseSubtractCsrCPUKernel(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y, + SparseCsrTensor* out) +``` + + +``` +void ElementWiseSubtractCooKernel(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y, + SparseCooTensor* out) ``` ``` -//暂定 -void SubtractCsrGradKernel(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y, - const SparseCsrTensor& dout, - SparseCsrTensor* dx, - SparseCsrTensor* dy); +void ElementWiseSubtractCsrGradKernel(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y, + const SparseCsrTensor& dout, + SparseCsrTensor* dx, + SparseCsrTensor* dy); + +``` +``` +void ElementWiseSubtractCooGradKernel(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y, + const SparseCooTensor& dout, + SparseCooTensor* dx, + SparseCooTensor* dy); ``` 函数设计为 ``` -SparseCooTensor Subtract(const Context& dev_ctx, - const SparseCooTensor& x, - const SparseCooTensor& y); +SparseCsrTensor ElementWiseSubtractCsr(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y) ``` 和 ``` -SparseCsrTensor Subtract(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y); +SparseCooTensor ElementWiseSubtractCoo(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y) ``` ## 底层OP设计 -新增一个sparse elementwise 的功能模块(暂定),然后使用已有op组合实现, 主要涉及`SparseCooToCsrKernel`和`SparseCsrToCooKernel`。 +实现对应的 CPU Kernel,使用 Merge 两个有序数组的算法,然后使用已有op组合实现, 主要涉及`SparseCooToCsrKernel`和`SparseCsrToCooKernel`。 + +对于dense tensor,值连续的存储在一块内存中,二元运算需要处理每一个元素,即`x[i][j] ∘ y[i][j]`,运算时间复杂度为 `O(numel(x))`, +`numel(x)`为`x`中总素个数。 + +而sparse tensor以索引和值的模式存储一个多数元素为零的tensor,二元运算只需要处理两个输入不全为0的位置, +在sparse tensor构造时,索引按升序排序,可以采取merge有序数组的方式,若两输入索引相等,则计算`x[i][j] ∘ y[i][j]`, +若不相等则说明该位置上的二元运算有一个元为0, +`x`索引小时计算 `x[i][j] ∘ 0`,`y`索引小时计算 `0 ∘ y[i][j]`。 +计算过的位置存储在新的索引数组中,这样,索引没有覆盖到的位置依然为0,节省了计算开销,时间复杂度为`O(nnz(x) + nnz(y))`, +`nnz(x)`为`x`中非零元素个数。 ## API实现方案 -主要参考scipy实现,将coo转换成csr再进行减法,然后转换回coo +对于SparseCsrTensor,将csr格式转换成coo格式再进行运算,然后转换回csr格式输出。 + +对于SparseCooTensor,直接进行运算。 # 六、测试和验收的考量 测试考虑的case如下: - 数值正确性 +- 反向 +- 不同 `sparse_dim` # 七、可行性分析及规划排期 -方案主要依赖paddle现有op组合而成 +方案主要依赖paddle现有op组合而成,并自行实现核心算法 # 八、影响面 diff --git a/rfcs/APIs/20220329_api_design_for_sparse_add.md b/rfcs/APIs/20220329_api_design_for_sparse_add.md index 2385af587..14615225b 100644 --- a/rfcs/APIs/20220329_api_design_for_sparse_add.md +++ b/rfcs/APIs/20220329_api_design_for_sparse_add.md @@ -1,12 +1,12 @@ # paddle.sparse.add 设计文档 -|API名称 | paddle.sparse.add | -|---|-----------------------------------------------------------| -|提交作者 | PeachML | -|提交时间 | 2022-03-29 | -|版本号 | V1.0 | -|依赖飞桨版本 | develop | -|文件名 | 20220329_api_design_for_sparse_add.md
| +| API名称 | paddle.sparse.add | +|----------------------------------------------------------|-------------------------------------------| +| 提交作者 | PeachML | +| 提交时间 | 2022-03-29 | +| 版本号 | V1.0 | +| 依赖飞桨版本 | develop | +| 文件名 | 20220329_api_design_for_sparse_add.md
| # 一、概述 @@ -141,7 +141,7 @@ void csr_binop_csr_general(const I n_row, const I n_col, # 四、对比分析 -torch设计结构复杂,为了适配paddle phi库的设计模式,故采用scipy的实现方式 +torch设计结构复杂,为了适配paddle phi库的设计模式,故参考scipy的实现方式 # 五、方案设计 @@ -150,54 +150,83 @@ torch设计结构复杂,为了适配paddle phi库的设计模式,故采用sc 在paddle/phi/kernels/sparse/目录下, kernel设计为 ``` -void AddCsrKernel(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y, - SparseCsrTensor* out); +void ElementWiseAddCsrKernel(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y, + SparseCsrTensor* out) +``` + + +``` +void ElementWiseAddCooKernel(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y, + SparseCooTensor* out) ``` ``` -//暂定 -void AddCsrGradKernel(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y, - const SparseCsrTensor& dout, - SparseCsrTensor* dx, - SparseCsrTensor* dy); +void ElementWiseAddCsrGradKernel(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y, + const SparseCsrTensor& dout, + SparseCsrTensor* dx, + SparseCsrTensor* dy); +``` +``` +void ElementWiseAddCooGradKernel(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y, + const SparseCooTensor& dout, + SparseCooTensor* dx, + SparseCooTensor* dy); ``` 函数设计为 ``` -SparseCooTensor Add(const Context& dev_ctx, - const SparseCooTensor& x, - const SparseCooTensor& y); +SparseCsrTensor ElementWiseAddCsr(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y) ``` 和 ``` -SparseCsrTensor Add(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y); +SparseCooTensor ElementWiseAddCoo(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y) ``` ## 底层OP设计 -新增一个sparse elementwise 的功能模块(暂定),然后使用已有op组合实现, 主要涉及`SparseCooToCsrKernel`和`SparseCsrToCooKernel`。 +实现对应的 CPU Kernel,使用 Merge 两个有序数组的算法,然后使用已有op组合实现, 主要涉及`SparseCooToCsrKernel`和`SparseCsrToCooKernel`。 + +对于dense tensor,值连续的存储在一块内存中,二元运算需要处理每一个元素,即`x[i][j] ∘ y[i][j]`,运算时间复杂度为 `O(numel(x))`, +`numel(x)`为`x`中总素个数。 + +而sparse tensor以索引和值的模式存储一个多数元素为零的tensor,二元运算只需要处理两个输入不全为0的位置, +在sparse tensor构造时,索引按升序排序,可以采取merge有序数组的方式,若两输入索引相等,则计算`x[i][j] ∘ y[i][j]`, +若不相等则说明该位置上的二元运算有一个元为0, +`x`索引小时计算 `x[i][j] ∘ 0`,`y`索引小时计算 `0 ∘ y[i][j]`。 +计算过的位置存储在新的索引数组中,这样,索引没有覆盖到的位置依然为0,节省了计算开销,时间复杂度为`O(nnz(x) + nnz(y))`, +`nnz(x)`为`x`中非零元素个数。 ## API实现方案 -主要参考scipy实现,将coo转换成csr再进行加法,然后转换回coo +对于SparseCsrTensor,将csr格式转换成coo格式再进行运算,然后转换回csr格式输出。 + +对于SparseCooTensor,直接进行运算。 # 六、测试和验收的考量 测试考虑的case如下: - 数值正确性 +- 反向 +- 不同 `sparse_dim` # 七、可行性分析及规划排期 -方案主要依赖paddle现有op组合而成 +方案主要依赖paddle现有op组合而成,并自行实现核心算法 # 八、影响面 diff --git a/rfcs/APIs/20220329_api_design_for_sparse_divide.md b/rfcs/APIs/20220329_api_design_for_sparse_divide.md index f75de08a7..98b288824 100644 --- a/rfcs/APIs/20220329_api_design_for_sparse_divide.md +++ b/rfcs/APIs/20220329_api_design_for_sparse_divide.md @@ -1,12 +1,12 @@ # paddle.sparse.divide 设计文档 -|API名称 | paddle.sparse.divide | - |----------------------------------------------|-----------------------------------------------------------| -|提交作者 | PeachML | -|提交时间 | 2022-03-29 | -|版本号 | V1.0 | -|依赖飞桨版本 | develop | -|文件名 | 20220329_api_design_for_sparse_divide.md
| +| API名称 | paddle.sparse.divide | +|----------------------------------------------------------|----------------------------------------------| +| 提交作者 | PeachML | +| 提交时间 | 2022-03-29 | +| 版本号 | V1.0 | +| 依赖飞桨版本 | develop | +| 文件名 | 20220329_api_design_for_sparse_divide.md
| # 一、概述 @@ -141,65 +141,98 @@ Scipy中有csr类型的稀疏矩阵,可以支持相除操作,通过`binary_o # 四、对比分析 -torch设计结构复杂,为了适配paddle phi库的设计模式,故采用scipy的实现方式 +torch设计结构复杂,为了适配paddle phi库的设计模式,故参考scipy的实现方式 # 五、方案设计 ## 命名与参数设计 -在paddle/phi/kernels/sparse/目录下,在paddle/phi/kernels/sparse/目录下, kernel设计为 +在paddle/phi/kernels/sparse/目录下, kernel设计为 ``` -void DivideCsrKernel(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y, - SparseCsrTensor* out); +void ElementWiseDivideCsrCPUKernel(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y, + SparseCsrTensor* out) ``` ``` -//暂定 -void DivideGradKernel(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y, - const SparseCsrTensor& out, - const SparseCsrTensor& dout, - SparseCsrTensor* dx, - SparseCsrTensor* dy); +void ElementWiseDivideCooKernel(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y, + SparseCooTensor* out) +``` + +``` +template +void ElementWiseDivideCsrGradKernel(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y, + const SparseCsrTensor& out, + const SparseCsrTensor& dout, + SparseCsrTensor* dx, + SparseCsrTensor* dy); +``` + +``` +void ElementWiseDivideCooGradKernel(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y, + const SparseCooTensor& out, + const SparseCooTensor& dout, + SparseCooTensor* dx, + SparseCooTensor* dy); ``` 函数设计为 ``` -SparseCooTensor Divide(const Context& dev_ctx, - const SparseCooTensor& x, - const SparseCooTensor& y); +SparseCsrTensor ElementWiseDivideCsr(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y) ``` 和 ``` -SparseCsrTensor Divide(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y); +SparseCooTensor ElementWiseDivideCoo(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y) ``` ## 底层OP设计 -新增一个sparse elementwise 的功能模块(暂定),然后使用已有op组合实现, 主要涉及`SparseCooToCsrKernel`和`SparseCsrToCooKernel`。 +实现对应的 CPU Kernel,使用 Merge 两个有序数组的算法,然后使用已有op组合实现, 主要涉及`SparseCooToCsrKernel`和`SparseCsrToCooKernel`。 + +对于dense tensor,值连续的存储在一块内存中,二元运算需要处理每一个元素,即`x[i][j] ∘ y[i][j]`,运算时间复杂度为 `O(numel(x))`, +`numel(x)`为`x`中总素个数。 + +而sparse tensor以索引和值的模式存储一个多数元素为零的tensor,二元运算只需要处理两个输入不全为0的位置, +在sparse tensor构造时,索引按升序排序,可以采取merge有序数组的方式,若两输入索引相等,则计算`x[i][j] ∘ y[i][j]`, +若不相等则说明该位置上的二元运算有一个元为0, +`x`索引小时计算 `x[i][j] ∘ 0`,`y`索引小时计算 `0 ∘ y[i][j]`。 +对于除法而言,两个输入都为0的位置运算结果不为0,所以需要将`y`中索引未覆盖到的位置(原tensor中为0),在运算中通过指向一个零常量的方式填充为0, +以参与除法运算。 +此时,时间复杂度为`O(numel(x))`,鉴于实际场景中动辄50% ~ 99%的稀疏性 [[1]][1] , +虽然时间复杂度与dense tensor一样,但是可以节省大量的存储空间。 ## API实现方案 -主要参考scipy实现,将coo转换成csr再进行除法,然后转换回coo +对于SparseCsrTensor,将csr格式转换成coo格式再进行运算,然后转换回csr格式输出。 + +对于SparseCooTensor,直接进行运算。 # 六、测试和验收的考量 测试考虑的case如下: - 数值正确性 +- 反向 +- 不同 `sparse_dim` # 七、可行性分析及规划排期 -方案主要依赖paddle现有op组合而成 +方案主要依赖paddle现有op组合而成,并自行实现核心算法 # 八、影响面 @@ -211,4 +244,6 @@ SparseCsrTensor Divide(const Context& dev_ctx, # 附件及参考资料 -无 \ No newline at end of file +[[1]: 深度学习中的稀疏性][1] + +[1]: https://sinews.siam.org/Details-Page/the-future-of-deep-learning-will-be-sparse diff --git a/rfcs/APIs/20220329_api_design_for_sparse_multiply.md b/rfcs/APIs/20220329_api_design_for_sparse_multiply.md index edb54cea8..df5fb226c 100644 --- a/rfcs/APIs/20220329_api_design_for_sparse_multiply.md +++ b/rfcs/APIs/20220329_api_design_for_sparse_multiply.md @@ -1,12 +1,12 @@ # paddle.sparse.multiply 设计文档 -|API名称 | paddle.sparse.multiply | - |----------------------------------------|-----------------------------------------------------------| -|提交作者 | PeachML | -|提交时间 | 2022-03-29 | -|版本号 | V1.0 | -|依赖飞桨版本 | develop | -|文件名 | 20220329_api_design_for_sparse_multiply.md
| +| API名称 | paddle.sparse.multiply | +|----------------------------------------------------------|------------------------------------------------| +| 提交作者 | PeachML | +| 提交时间 | 2022-03-29 | +| 版本号 | V1.0 | +| 依赖飞桨版本 | develop | +| 文件名 | 20220329_api_design_for_sparse_multiply.md
| # 一、概述 @@ -141,7 +141,7 @@ Scipy中有csr类型的稀疏矩阵,可以支持相乘操作,通过`binary_o # 四、对比分析 -torch设计结构复杂,为了适配paddle phi库的设计模式,故采用scipy的实现方式 +torch设计结构复杂,为了适配paddle phi库的设计模式,故参考scipy的实现方式 # 五、方案设计 @@ -150,55 +150,86 @@ torch设计结构复杂,为了适配paddle phi库的设计模式,故采用sc 在paddle/phi/kernels/sparse/目录下, kernel设计为 ``` -void MultiplyCsrKernel(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y, - SparseCsrTensor* out); +void ElementWiseMultiplyCsrCPUKernel(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y, + SparseCsrTensor* out) ``` + +``` +void ElementWiseMultiplyCooKernel(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y, + SparseCooTensor* out) +``` + +``` +template +void ElementWiseMultiplyCsrGradKernel(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y, + const SparseCsrTensor& dout, + SparseCsrTensor* dx, + SparseCsrTensor* dy); ``` -//暂定 -void MultiplyCsrGradKernel(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y, - const SparseCsrTensor& dout, - SparseCsrTensor* dx, - SparseCsrTensor* dy) + +``` +void ElementWiseMultiplyCooGradKernel(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y, + const SparseCooTensor& dout, + SparseCooTensor* dx, + SparseCooTensor* dy); ``` 函数设计为 ``` -SparseCooTensor Multiply(const Context& dev_ctx, - const SparseCooTensor& x, - const SparseCooTensor& y); +SparseCsrTensor ElementWiseMultiplyCsr(const Context& dev_ctx, + const SparseCsrTensor& x, + const SparseCsrTensor& y) ``` 和 ``` -SparseCsrTensor Multiply(const Context& dev_ctx, - const SparseCsrTensor& x, - const SparseCsrTensor& y); +SparseCooTensor ElementWiseMultiplyCoo(const Context& dev_ctx, + const SparseCooTensor& x, + const SparseCooTensor& y) ``` ## 底层OP设计 -新增一个sparse elementwise 的功能模块(暂定),然后使用已有op组合实现, 主要涉及`SparseCooToCsrKernel`和`SparseCsrToCooKernel`。 +实现对应的 CPU Kernel,使用 Merge 两个有序数组的算法,然后使用已有op组合实现, 主要涉及`SparseCooToCsrKernel`和`SparseCsrToCooKernel`。 + +对于dense tensor,值连续的存储在一块内存中,二元运算需要处理每一个元素,即`x[i][j] ∘ y[i][j]`,运算时间复杂度为 `O(numel(x))`, +`numel(x)`为`x`中总素个数。 + +而sparse tensor以索引和值的模式存储一个多数元素为零的tensor,二元运算只需要处理两个输入不全为0的位置, +在sparse tensor构造时,索引按升序排序,可以采取merge有序数组的方式,若两输入索引相等,则计算`x[i][j] ∘ y[i][j]`, +若不相等则说明该位置上的二元运算有一个元为0, +`x`索引小时计算 `x[i][j] ∘ 0`,`y`索引小时计算 `0 ∘ y[i][j]`。 +计算过的位置存储在新的索引数组中,这样,索引没有覆盖到的位置依然为0,节省了计算开销,时间复杂度为`O(nnz(x) + nnz(y))`, +`nnz(x)`为`x`中非零元素个数。 ## API实现方案 -主要参考scipy实现,将coo转换成csr再进行乘法,然后转换回coo +对于SparseCsrTensor,将csr格式转换成coo格式再进行运算,然后转换回csr格式输出。 + +对于SparseCooTensor,直接进行运算。 # 六、测试和验收的考量 测试考虑的case如下: - 数值正确性 +- 反向 +- 不同 `sparse_dim` # 七、可行性分析及规划排期 -方案主要依赖paddle现有op组合而成 +方案主要依赖paddle现有op组合而成,并自行实现核心算法 # 八、影响面