forked from FT_DSP/FT_DSP.gitlink.net
178 lines
8.7 KiB
ReStructuredText
178 lines
8.7 KiB
ReStructuredText
ScatterElements
|
||
=================
|
||
|
||
返回一个新tensor,根据指定索引和更新值对input中的元素进行指定操作(替换或相加)。不支持隐式类型转换。举例:一个三维输入tensor的返回为:
|
||
|
||
.. code-block:: python
|
||
|
||
output[indices[i][j][k]][j][k] = updates[i][j][k] #if axis == 0, reduction == "none"
|
||
output[i][indices[i][j][k]][k] += updates[i][j][k] #if axis == 1, reduction == "add"
|
||
output[i][j][indices[i][j][k]] = updates[i][j][k] #if axis == 2, reduction == "none"
|
||
|
||
输入:
|
||
- **input** - 输入数据的地址
|
||
- **indices** - 指定索引。
|
||
- **updates** - 更新值。
|
||
- **param** - 算子计算所需参数的结构体。其各成员见下述。
|
||
- **core_mask** - 核掩码。
|
||
|
||
**ScatterElementsParameter定义:**
|
||
|
||
.. code-block:: c
|
||
:linenos:
|
||
|
||
typedef struct ScatterElementsParameter {
|
||
int* indices_stride_; // 对应于indices数组每一维度的步长
|
||
int* output_stride_; // 对应于output数组每一维度的步长
|
||
int input_dims_; // 输入张量的维度数
|
||
int axis_; // 指定索引所在的轴
|
||
int input_axis_size_; // 索引所在轴的元素数
|
||
int indices_total_num_; // indices数组的总元素数
|
||
int input_total_num_; // input数组的总元素数
|
||
int reduction_type_; // 规约类型,0代表none,1代表add
|
||
} ScatterElementsParameter;
|
||
|
||
输出:
|
||
- **output** - 输出地址。
|
||
|
||
支持平台:
|
||
``FT78NE``
|
||
``MT7004``
|
||
|
||
.. note::
|
||
- FT78NE 支持int8, int16, int32, fp32, fp64, cplx64, cplx128
|
||
- MT7004 支持fp16, fp32, int16, int32, cplx64
|
||
- 如果 indices 中有多个索引向量对应于同一位置,则输出中该位置值是不确定的。
|
||
- 如果 indices 的值超出 input 索引上下界,则相应的 updates 不会更新到 input,也不会抛出索引错误。
|
||
|
||
**共享存储版本:**
|
||
|
||
.. c:function:: void i8_scatter_elements_s(int8_t* input, int8_t* output, int* indices, int8_t* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void i16_scatter_elements_s(int16_t* input, int16_t* output, int* indices, int16_t* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void i32_scatter_elements_s(int* input, int* output, int* indices, int* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void hp_scatter_elements_s(half* input, half* output, int* indices, half* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void fp_scatter_elements_s(float* input, float* output, int* indices, float* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void dp_scatter_elements_s(double* input, double* output, int* indices, double* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void c64_scatter_elements_s(float* input, float* output, int* indices, float* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void c128_scatter_elements_s(double* input, double* output, int* indices, double* updates, ScatterElementsParameter* param, int core_mask)
|
||
|
||
**C调用示例:**
|
||
|
||
.. code-block:: c
|
||
:linenos:
|
||
:emphasize-lines: 40
|
||
|
||
void PackParam(ScatterElementsParameter* param, int* indices_shape, int* input_shape) {
|
||
param->indices_stride_[param->input_dims_ - 1] = 1;
|
||
int i;
|
||
for (i = param->input_dims_ - 1; i > 0; --i) {
|
||
param->indices_stride_[i - 1] = param->indices_stride_[i] * indices_shape[i];
|
||
}
|
||
param->output_stride_[param->input_dims_ - 1] = 1;
|
||
for (i = param->input_dims_ - 1; i > 0; --i) {
|
||
param->output_stride_[i - 1] = param->output_stride_[i] * input_shape[i];
|
||
}
|
||
param->indices_total_num_ = 1;
|
||
for (i = 0; i < param->input_dims_; i++) {
|
||
param->indices_total_num_ *= indices_shape[i];
|
||
}
|
||
param->input_total_num_ = 1;
|
||
for (i = 0; i < param->input_dims_; i++) {
|
||
param->input_total_num_ *= input_shape[i];
|
||
}
|
||
param->input_axis_size_ = input_shape[param->axis_];
|
||
}
|
||
|
||
void TestScatterElementsSMC(int* input_shape, int* indices_shape, int ndim, int axis, int reduction_type, int core_mask) {
|
||
int core_num = GetCoreNum(core_mask);
|
||
int core_id = get_core_id();
|
||
int logic_core_id = GetLogicCoreId(core_mask, core_id);
|
||
void* input_data = (void*)0x88000000;
|
||
void* output_data = (void*)0x98000000;
|
||
int* indices_data = (int*)0xA8000000;
|
||
void* updates_data = (void*)0xB8000000;
|
||
ScatterElementsParameter* param = (ScatterElementsParameter*)0xC8000000;
|
||
if (logic_core_id == 0) {
|
||
param->axis_ = axis;
|
||
param->input_dims_ = ndim;
|
||
param->indices_stride_ = (int*)0xC8020000;
|
||
param->output_stride_ = (int*)0xC8040000;
|
||
param->reduction_type_ = reduction_type;
|
||
PackParam(param, indices_shape, input_shape);
|
||
}
|
||
sys_bar(0, core_num); // 初始化参数完成后进行同步
|
||
fp_scatter_elements_s(input_data, output_data, indices_data, updates_data, param, core_mask);
|
||
}
|
||
|
||
void main() {
|
||
int input_shape[2] = {8, 30};
|
||
int indices_shape[2] = {3, 3};
|
||
int ndim = 2;
|
||
int axis = 0;
|
||
int reduction_type = 0;
|
||
int core_mask = 0b1111;
|
||
TestScatterElementsSMC(input_shape, indices_shape, ndim, axis, reduction_type, core_mask);
|
||
}
|
||
|
||
**私有存储版本:**
|
||
|
||
.. c:function:: void i8_scatter_elements_p(int8_t* input, int8_t* output, int* indices, int8_t* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void i16_scatter_elements_p(int16_t* input, int16_t* output, int* indices, int16_t* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void i32_scatter_elements_p(int* input, int* output, int* indices, int* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void hp_scatter_elements_p(half* input, half* output, int* indices, half* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void fp_scatter_elements_p(float* input, float* output, int* indices, float* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void dp_scatter_elements_p(double* input, double* output, int* indices, double* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void c64_scatter_elements_p(float* input, float* output, int* indices, float* updates, ScatterElementsParameter* param, int core_mask)
|
||
.. c:function:: void c128_scatter_elements_p(double* input, double* output, int* indices, double* updates, ScatterElementsParameter* param, int core_mask)
|
||
|
||
**C调用示例:**
|
||
|
||
.. code-block:: c
|
||
:linenos:
|
||
:emphasize-lines: 34
|
||
|
||
void PackParam(ScatterElementsParameter* param, int* indices_shape, int* input_shape) {
|
||
param->indices_stride_[param->input_dims_ - 1] = 1;
|
||
int i;
|
||
for (i = param->input_dims_ - 1; i > 0; --i) {
|
||
param->indices_stride_[i - 1] = param->indices_stride_[i] * indices_shape[i];
|
||
}
|
||
param->output_stride_[param->input_dims_ - 1] = 1;
|
||
for (i = param->input_dims_ - 1; i > 0; --i) {
|
||
param->output_stride_[i - 1] = param->output_stride_[i] * input_shape[i];
|
||
}
|
||
param->indices_total_num_ = 1;
|
||
for (i = 0; i < param->input_dims_; i++) {
|
||
param->indices_total_num_ *= indices_shape[i];
|
||
}
|
||
param->input_total_num_ = 1;
|
||
for (i = 0; i < param->input_dims_; i++) {
|
||
param->input_total_num_ *= input_shape[i];
|
||
}
|
||
param->input_axis_size_ = input_shape[param->axis_];
|
||
}
|
||
|
||
void TestScatterElementsL2(int* input_shape, int* indices_shape, int ndim, int axis, int reduction_type, int core_mask) {
|
||
void* input_data = (void*)0x10000000; // 私有存储版本地址设置在AM内
|
||
void* output_data = (void*)0x10001000;
|
||
int* indices_data = (int*)0x10002000;
|
||
void* updates_data = (void*)0x10003000;
|
||
ScatterElementsParameter* param = (ScatterElementsParameter*)0x10004000;
|
||
param->axis_ = axis;
|
||
param->input_dims_ = ndim;
|
||
param->indices_stride_ = (int*)0x10005000;
|
||
param->output_stride_ = (int*)0x10006000;
|
||
param->reduction_type_ = reduction_type;
|
||
PackParam(param, indices_shape, input_shape);
|
||
fp_scatter_elements_p(input_data, output_data, indices_data, updates_data, param, core_mask);
|
||
}
|
||
|
||
void main() {
|
||
int input_shape[2] = {8, 30};
|
||
int indices_shape[2] = {3, 3};
|
||
int ndim = 2;
|
||
int axis = 0;
|
||
int reduction_type = 0;
|
||
int core_mask = 0b0001; // 私有存储版本只能设置为一个核心启动
|
||
TestScatterElementsL2(input_shape, indices_shape, ndim, axis, reduction_type, core_mask);
|
||
} |