Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature](mluOpDynamicPointToVoxelBackward): to be better performance #1142

Merged
merged 3 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
| 版本号 | 修订人 | 修订日期 | 修订描述 |
| ----- | ----- | ------ | ------- |
| V1.0 | xuminjie | 2023 | 首次提交 |
| V1.1 | wangyuan | 2024.11.08 | 修复sync、算法时序引入的潜在缺陷 |

- #### 内容描述

Expand Down Expand Up @@ -80,10 +81,10 @@ max模式:根据point2voxel_map,分组找出feats和voxel_feats中值相同
| 输入限制 | 输入 `grad_voxel_feats`, `feats`, `voxel_feats`支持输入 nan 或 inf |
| 输入参数限制 | 仅支持输入reduce_mode值为MLUOP_REDUCEMODE_MAX |
| 数据类型限制 | 输入 `grad_voxel_feats`, `feats`, `voxel_feats` 输出 `grad_feats` 数据类型保持一致;`point2voxel_map`, `voxel_points_count`, `voxel_num`数据类型保持一致 |
| 布局限制 | 无 |
| 原位限制 | 不支持原位 |
| 布局限制 | 无 |
| 原位限制 | 不支持原位 |
| stride 限制 | 不支持 stride 机制 |
| 广播限制 | 不支持广播 |
| 广播限制 | 不支持广播 |

### 1.5 验收标准

Expand Down Expand Up @@ -167,7 +168,26 @@ mluOpStatus_t MLUOP_WIN_API mluOpGetDynamicPointToVoxelBackwardWorkspaceSize(

#### 3.1.1 计算原理说明

`dynamic_point_to_voxel_backward` 算子包含7个输入:`reduce_type`、`grad_voxel_feats`、`feats`、`voxel_feats`、`point2voxel_map`、`voxel_point2_count`、`voxel_num`,1个输出:`grad_feats`; 根据 1.2 节算子功能, 可将算子2部分分为2个kernel来实现:
`dynamic_point_to_voxel_backward` 算子包含7个输入,1个输出。

input:
1. `grad_feats`,`shape=[N,C]`
2. `grad_voxel_feats`,`shape=[M,C]`
3. `voxel_feats`,`shape=[M,C]`
4. `point2voxel_map`,`shape=[N]`
5. `voxel_point2_count`,`shape=[M]`
6. `voxel_num`,`hape=[1]`
7. `reduce_type`

output:
1. `grad_feats`,`shape=[N,C]`

`dynamic_point_to_voxel_forward` 中:
- `coor` 表示 N 个点云数据对应在三维(三维体素网格坐标)具体坐标信息,`feats` 表示有 N 个点云数据,每个点云有 C 个特征
- `feats`、`coors` 中数据是一一对应的
- 该算子将全正坐标外坐标刷-1、去重、排序后,通过 `reduce_mode` ,对 `feats` 中数据进行处理

根据 1.2 节算子功能,可将`dynamic_point_to_voxel_forwardcoors` 分为2个kernel来实现:
mahxn0 marked this conversation as resolved.
Show resolved Hide resolved

- #### 计算逻辑层面

Expand All @@ -176,7 +196,22 @@ mluOpStatus_t MLUOP_WIN_API mluOpGetDynamicPointToVoxelBackwardWorkspaceSize(

先将`voxel_from`初始化成最大值N;

根据`point2voxel_map`中记录的“特征与体素特征的映射关系”。对比输入的特征`feats`和体素特征 `voxel_feats`,对于第i个体素特征`voxel_feats[i]`,如果第j个特征与之相等,则认为这个体素特征是由该特征得到的。在中间结果`voxel_from`中保存两者的下标关系,使`voxel_from[i]=j`,该中间结果使用workspace保存。
根据`point2voxel_map`中记录的“特征与体素特征的映射关系”。对比输入的特征`feats`和体素特征 `voxel_feats`:
1. 对于第 `i` 个体素特征中 `c(c=0,1,2,...,C-1)` 维特征 `voxel_feats[i,c]`,若与第 `j` 个特征的 `c` 维特征的 `feats[j, c]`相等,则认为这个体素特征是由该特征得到的
2. 若 `voxel_feats[i,c]` 与多个特征 `feats[j, c]`、`feats[k, c]` 相等,此时认为下标靠前的特征`feats[j, c]`(`j<k`)是 `voxel_feats[i,c]` 对应点
3. 新建 `voxel_from` 保存上述两者的下标关系
4. 举个简单例子
```c++
// feats 中数据在 voxel_feats 中的映射如下
point2voxel_map = [0, 0, 1, 1, 2, 3, ...]

// 依据映射关系 load feats,voxel_feats
deal_feats = [feats[0], feats[1], feats[2], feats[3],...,]
dead_voxel_feats = [voxel_feats[0], voxel_feats[0], voxel_feats[1], voxel_feats[1], voxel_feats[2],...]

// 计算映射下标 voxel_from,对于多个 feats[j] 相同,取其中最小值
voxel_from = [0, 2, 4, 5, ...]
```

- kernel2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ grid\_z = round((coors\_z\_max - coors\_z\_min) / voxel\_z)

利用点云的位置信息可进一步获取其在三维空间中对应的体素坐标。其计算公式如下:

1)feats: [N, C], 表示有 N 个点云数据,每个点云有 C 个特征;
1)`feats`: [N, C], 表示有 N 个点云数据,每个点云有 C 个特征;

2)point_coors: [N, 3], 表示 N 个点云数据对应在三维空间中具体坐标信息
2)`point_coors`: [N, 3], 表示 N 个点云数据对应在三维空间中具体坐标信息,`feats`与`coors` 中数据是一一对应的

将点云所在三维空间坐标信息转为三维体素网格坐标,则该点所在体素坐标 (c_x, c_y, c_z) 的计算公式为:

Expand All @@ -100,40 +100,57 @@ c\_z = floorf((point_coors[idx][2] - coors\_z\_min) / voxel\_z)
1)对 `coors` 体素坐标进行有效值检查,如果 `coors` 中 x、y、z 的值有一个小于 0 则都赋值为 -1;

```c++
coors: [[-3,5,2],[-2,1,4],[6,7,8],[2,4,6]]
coors: [[-3,5,2],[-2,1,4],[6,7,8],[6,7,8],[2,4,6]]
result:
coors: [[-1,-1,-1],[-1,-1,-1],[6,7,8],[2,4,6]]
coors: [[-1,-1,-1],[-1,-1,-1],[6,7,8],[6,7,8],[2,4,6]]
```

2)将体素坐标 `coors` 进行排序、去重,得到新的体素坐标 `voxel_coors`; 保存去重后体素的个数 num_voxels 到 `voxel_num`; 保存 `coors` 中每个体素坐标在 `voxel_coors` 中对应的索引到 `point2voxel_map`; 保存 `voxel_coors` 中每个体素坐标在 `coors` 中出现的个数到 `voxel_points_count`;

![point2voxel](./point2voxel.png)

该步骤其实是 `unique` 操作:
- `mode = sort`
- `input` 为 `coors`
- `output` 为 `voxel_coors`
- `indices` 为 `point2voxel_map`
- `count` 为 `voxel_num`

```c++
coors: [[-1,-1,-1],[-1,-1,-1],[6,7,8],[2,4,6]]
coors: [[-1,-1,-1],[-1,-1,-1],[6,7,8],[6,7,8],[2,4,6]]

result:
voxel_coors: [[-1,-1,-1],[6,7,8],[2,4,6]]
point2voxel_map:[0,0,1,2]
voxel_points_count: [2,1,1]
voxel_coors: [[-1,-1,-1],[2,4,6],[6,7,8]] // 坐标 coors 进行排序、去重
point2voxel_map:[0,0,2,1,1] // 记录 coors 中元素在 voxel_coors 中的 idx
voxel_points_count: [2,1,2] // 记录 voxel_coors 每个元素的 count
voxel_num:[3]
```

3)如果 `voxel_coors[0][0]` 小于 0,则对 2)中输出进行修整;
3)如果 `voxel_coors[i,:], i=0,1,2,...` 中包含小于 `0` 元素,则删除 `voxel_coors[i,:]` 以及 `voxel_points_count` 中对应 `count`,同时 `point2voxel_map -= 1`

```c++
voxel_coors: [[-1,-1,-1],[6,7,8],[2,4,6]]
point2voxel_map:[0,0,1,2]
voxel_points_count: [2,1,1]
voxel_num:[3]
result:
voxel_coors: [[6,7,8],[2,4,6]]
point2voxel_map:[-1,-1,0,1]
voxel_points_count: [1,1]
voxel_coors: [[2,4,6],[6,7,8]]
point2voxel_map:[-1,-1,1,1,0]
voxel_points_count: [1,2]
voxel_num:[2]
```

4)遍历 `feats` 中每个点,在特征维度上,对每个值根据 `reduce_type` 的方法进行计算,将结果保存到 `voxel_feats` 中; 当 `reduce_type` = `max`, 在特征维度上对每个值取最大的值; 当 `reduce_type` = `mean`, 将特征维度每个值都累加到 `voxel_feats` 对应位置中,再利用 `voxel_points_count` 获取该体素位置在原始体素中出现的个数,再对 `voxel_feats` 的特征维度求平均。

```c++
coors: [[-1,-1,-1],[-1,-1,-1],[6,7,8],[6,7,8],[2,4,6]]
voxel_coors: [[2,4,6],[6,7,8]]
point2voxel_map:[-1,-1,1,1,0]

// point2voxel_map 中 0,1 为-1,表示该位置 feats 数据无效
// 以 reduce_type=max 为例:
// voxel_feats[0] 为 point2voxel_map 中 0 值对应的 feats 进行reduce
// voxel_feats[1] 为 point2voxel_map 中 1 值对应的 feats 进行reduce
voxel_feats[0, i] = max(feats[2,i], feats[3,i])
voxel_feats[1] = feats[4]
```

- #### nan/inf

1)feats 支持 nan/inf;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ mluOpStatus_t MLUOP_WIN_API mluOpDynamicPointToVoxelBackward(
CHECK_RETURN("[mluOpDynamicPointToVoxelBackward]",
KernelDynamicPointToVoxelBackward(
k_dim, k_type, handle->queue, feats, voxel_feats,
grad_feats, workspace, point2voxel_map, voxel_num, N, C));
workspace, point2voxel_map, voxel_num, N, C));
// 4. scatter
cnnlScatterNdMode_t scatter_mode = CNNL_SCATTERND_ADD;
mluOpTensorDescriptor_t updates_desc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ DYNAMIC_POINT_TO_VOXEL_BACKWARD_H

mluOpStatus_t MLUOP_WIN_API KernelDynamicPointToVoxelBackward(
cnrtDim3_t k_dim, cnrtFunctionType_t k_type, cnrtQueue_t queue,
const void *feats, const void *voxel_feats, void *grad_feats,
void *voxel_from, const void *point2voxel_map, const void *voxel_num,
const int N, const int C);
const void *feats, const void *voxel_feats, void *voxel_from,
const void *point2voxel_map, const void *voxel_num, const int N,
const int C);

#endif // KERNELS_DYNAMIC_POINT_TO_VOXEL_BACKWARD_
// DYNAMIC_POINT_TO_VOXEL_FORWARD_H
Loading
Loading