|
|
@ -64,6 +64,21 @@ void MatrixEmptyInt8(int8_t *dst, int row, int col) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void RowMajor2Row4x16MajorInt8(const int8_t *src_ptr, int8_t *dst_ptr, int row, int col) {
|
|
|
|
|
|
|
|
int col4 = UP_ROUND(col, C4NUM);
|
|
|
|
|
|
|
|
for (int r = 0; r < row; r++) {
|
|
|
|
|
|
|
|
int rd16 = r / C16NUM;
|
|
|
|
|
|
|
|
int rm16 = r % C16NUM;
|
|
|
|
|
|
|
|
for (int c = 0; c < col; c++) {
|
|
|
|
|
|
|
|
int cd4 = c / C4NUM;
|
|
|
|
|
|
|
|
int cm4 = c % C4NUM;
|
|
|
|
|
|
|
|
int dst_index = rd16 * col4 * C16NUM + cd4 * C16NUM * C4NUM + rm16 * C4NUM + cm4;
|
|
|
|
|
|
|
|
int src_index = r * col + c;
|
|
|
|
|
|
|
|
dst_ptr[dst_index] = src_ptr[src_index];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RowMajor2Row16x4MajorInt8(int8_t *src_ptr, int8_t *dst_ptr, int row, int col) {
|
|
|
|
void RowMajor2Row16x4MajorInt8(int8_t *src_ptr, int8_t *dst_ptr, int row, int col) {
|
|
|
|
/* Row-major to row16x4-major (block row-major) */
|
|
|
|
/* Row-major to row16x4-major (block row-major) */
|
|
|
|
int col16 = UP_ROUND(col, C16NUM);
|
|
|
|
int col16 = UP_ROUND(col, C16NUM);
|
|
|
@ -268,6 +283,223 @@ void MatMulInt8_8x8_r(const int8_t *a, const int8_t *b, int8_t *dst, size_t row,
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MatMulInt8_4x16_r(const int8_t *a, const int8_t *b, int8_t *dst, size_t row, size_t col, size_t deep_4,
|
|
|
|
|
|
|
|
size_t stride, const int32_t *input_sum, const int32_t *bias, int32_t *left_shift,
|
|
|
|
|
|
|
|
int32_t *right_shift, int32_t *multiplier, int32_t output_zp, int32_t mini, int32_t maxi,
|
|
|
|
|
|
|
|
size_t per_channel, int32_t *filter_zp) {
|
|
|
|
|
|
|
|
/* row4x4-major * row4x16-major => (int8)row-major */
|
|
|
|
|
|
|
|
for (int r = 0; r < row; r++) {
|
|
|
|
|
|
|
|
for (int c = 0; c < col; c++) {
|
|
|
|
|
|
|
|
int r4div = r / C4NUM, r4mod = r % C4NUM;
|
|
|
|
|
|
|
|
int c16div = c / C16NUM, c16mod = c % C16NUM;
|
|
|
|
|
|
|
|
size_t ci = r * col + c;
|
|
|
|
|
|
|
|
int32_t value = 0;
|
|
|
|
|
|
|
|
for (int d = 0; d < deep_4; d++) {
|
|
|
|
|
|
|
|
int d4div = d / C4NUM, d4mod = d % C4NUM;
|
|
|
|
|
|
|
|
size_t ai = r4div * deep_4 * C4NUM + d4div * C4NUM * C4NUM + r4mod * C4NUM + d4mod;
|
|
|
|
|
|
|
|
size_t bi = c16div * deep_4 * C16NUM + d4div * C16NUM * C4NUM + c16mod * C4NUM + d4mod;
|
|
|
|
|
|
|
|
value = value + a[ai] * b[bi];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t cur_input_sum = per_channel ? input_sum[r] * filter_zp[c] : input_sum[r];
|
|
|
|
|
|
|
|
value -= cur_input_sum;
|
|
|
|
|
|
|
|
value += bias[c];
|
|
|
|
|
|
|
|
int32_t cur_left_shift = per_channel ? left_shift[c] : left_shift[0];
|
|
|
|
|
|
|
|
int32_t cur_right_shift = per_channel ? right_shift[c] : right_shift[0];
|
|
|
|
|
|
|
|
int32_t cur_multiplier = per_channel ? multiplier[c] : multiplier[0];
|
|
|
|
|
|
|
|
value = MultiplyByQuantizedMultiplier(value, cur_multiplier, cur_left_shift, cur_right_shift) + output_zp;
|
|
|
|
|
|
|
|
value = MSMIN(maxi, value);
|
|
|
|
|
|
|
|
value = MSMAX(mini, value);
|
|
|
|
|
|
|
|
dst[ci] = (int8_t)value;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PackInput4x4AndInputSumPert(const int8_t *src_input, int8_t *packed_input, int32_t *input_sum,
|
|
|
|
|
|
|
|
size_t input_channel, size_t plane_size, int32_t filter_zp) {
|
|
|
|
|
|
|
|
int ic4 = UP_ROUND(input_channel, C4NUM);
|
|
|
|
|
|
|
|
int hw4 = UP_ROUND(plane_size, C4NUM);
|
|
|
|
|
|
|
|
size_t hw_4div = plane_size / C4NUM * C4NUM;
|
|
|
|
|
|
|
|
size_t ic_4div = input_channel / C4NUM * C4NUM;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const int8_t *src_r = src_input;
|
|
|
|
|
|
|
|
int8_t *pack_r = packed_input;
|
|
|
|
|
|
|
|
/* per layer */
|
|
|
|
|
|
|
|
for (int hwi = 0; hwi < hw_4div; hwi += C4NUM) {
|
|
|
|
|
|
|
|
const int8_t *src_ic = src_r;
|
|
|
|
|
|
|
|
int8_t *pack_ic = pack_r;
|
|
|
|
|
|
|
|
int32_t *input_sum_r = input_sum + hwi;
|
|
|
|
|
|
|
|
#ifdef ENABLE_ARM64
|
|
|
|
|
|
|
|
size_t src_stride = input_channel;
|
|
|
|
|
|
|
|
size_t ic_4res = input_channel - ic_4div;
|
|
|
|
|
|
|
|
asm volatile(
|
|
|
|
|
|
|
|
"dup v2.4s, wzr \n"
|
|
|
|
|
|
|
|
"mov x14, %[input_sum_r] \n"
|
|
|
|
|
|
|
|
"dup v3.4s, %w[filter_zp] \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"mov x10, %[src_ic] \n"
|
|
|
|
|
|
|
|
"mov x11, %[pack_ic] \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"mov x15, #0 \n"
|
|
|
|
|
|
|
|
"1: \n"
|
|
|
|
|
|
|
|
"cmp x15, %[ic_4div] \n"
|
|
|
|
|
|
|
|
"add x15, x15, #4\n"
|
|
|
|
|
|
|
|
"mov x12, x10 \n"
|
|
|
|
|
|
|
|
"add x10, x10, #4\n"
|
|
|
|
|
|
|
|
"blt 2f \n"
|
|
|
|
|
|
|
|
"cmp %[ic_4res], #0\n"
|
|
|
|
|
|
|
|
"beq 6f \n"
|
|
|
|
|
|
|
|
"cmp %[ic_4res], #1\n"
|
|
|
|
|
|
|
|
"beq 3f \n"
|
|
|
|
|
|
|
|
"cmp %[ic_4res], #2\n"
|
|
|
|
|
|
|
|
"beq 4f \n"
|
|
|
|
|
|
|
|
"cmp %[ic_4res], #3\n"
|
|
|
|
|
|
|
|
"beq 5f \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"2: \n"
|
|
|
|
|
|
|
|
"ld1 {v0.s}[0], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.s}[1], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.s}[2], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.s}[3], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"st1 {v0.16b}, [x11], #16\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"saddlp v1.8h, v0.16b \n"
|
|
|
|
|
|
|
|
"saddlp v0.4s, v1.8h \n"
|
|
|
|
|
|
|
|
"add v2.4s, v2.4s, v0.4s \n"
|
|
|
|
|
|
|
|
"b 1b \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"3: \n" /* ic res 1 */
|
|
|
|
|
|
|
|
"dup v0.4s, wzr \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"ld1 {v0.b}[0], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.b}[4], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.b}[8], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.b}[12], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"st1 {v0.16b}, [x11], #16\n"
|
|
|
|
|
|
|
|
"saddlp v1.8h, v0.16b \n"
|
|
|
|
|
|
|
|
"saddlp v0.4s, v1.8h \n"
|
|
|
|
|
|
|
|
"add v2.4s, v2.4s, v0.4s \n"
|
|
|
|
|
|
|
|
"b 6f \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"4: \n" /* ic res 2 */
|
|
|
|
|
|
|
|
"dup v0.4s, wzr \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"ld1 {v0.h}[0], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.h}[2], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.h}[4], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.h}[6], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"st1 {v0.16b}, [x11], #16\n"
|
|
|
|
|
|
|
|
"saddlp v1.8h, v0.16b \n"
|
|
|
|
|
|
|
|
"saddlp v0.4s, v1.8h \n"
|
|
|
|
|
|
|
|
"add v2.4s, v2.4s, v0.4s \n"
|
|
|
|
|
|
|
|
"b 6f \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"5: \n" /* ic res 3 */
|
|
|
|
|
|
|
|
"dup v0.4s, wzr \n"
|
|
|
|
|
|
|
|
"add x13, x12, #2 \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"ld1 {v0.h}[0], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.b}[2], [x13], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.h}[2], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.b}[6], [x13], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.h}[4], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.b}[10], [x13], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.h}[6], [x12], %[src_stride]\n"
|
|
|
|
|
|
|
|
"ld1 {v0.b}[14], [x13], %[src_stride]\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"st1 {v0.16b}, [x11], #16\n"
|
|
|
|
|
|
|
|
"saddlp v1.8h, v0.16b \n"
|
|
|
|
|
|
|
|
"saddlp v0.4s, v1.8h \n"
|
|
|
|
|
|
|
|
"add v2.4s, v2.4s, v0.4s \n"
|
|
|
|
|
|
|
|
"b 6f \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"6: \n"
|
|
|
|
|
|
|
|
"mul v2.4s, v2.4s, v3.4s \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"st1 {v2.4s}, [x14], #16 \n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:
|
|
|
|
|
|
|
|
: [ src_ic ] "r"(src_ic), [ pack_ic ] "r"(pack_ic), [ input_sum_r ] "r"(input_sum_r),
|
|
|
|
|
|
|
|
[ src_stride ] "r"(src_stride), [ ic_4div ] "r"(ic_4div), [ ic_4res ] "r"(ic_4res), [ filter_zp ] "r"(filter_zp)
|
|
|
|
|
|
|
|
: "x10", "x11", "x12", "x13", "x14", "x15", "v0", "v1", "v2", "v3");
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
int32_t tmp_sum_value[4] = {0};
|
|
|
|
|
|
|
|
for (int ici = 0; ici < ic_4div; ici += C4NUM) {
|
|
|
|
|
|
|
|
for (int i = 0; i < C4NUM; i++) {
|
|
|
|
|
|
|
|
tmp_sum_value[i] += src_ic[0 + i * input_channel];
|
|
|
|
|
|
|
|
tmp_sum_value[i] += src_ic[1 + i * input_channel];
|
|
|
|
|
|
|
|
tmp_sum_value[i] += src_ic[2 + i * input_channel];
|
|
|
|
|
|
|
|
tmp_sum_value[i] += src_ic[3 + i * input_channel];
|
|
|
|
|
|
|
|
pack_ic[0 + i * C4NUM] = src_ic[0 + i * input_channel];
|
|
|
|
|
|
|
|
pack_ic[1 + i * C4NUM] = src_ic[1 + i * input_channel];
|
|
|
|
|
|
|
|
pack_ic[2 + i * C4NUM] = src_ic[2 + i * input_channel];
|
|
|
|
|
|
|
|
pack_ic[3 + i * C4NUM] = src_ic[3 + i * input_channel];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
src_ic += C4NUM;
|
|
|
|
|
|
|
|
pack_ic += C4NUM * C4NUM;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int ici = ic_4div; ici < input_channel; ici += 1) {
|
|
|
|
|
|
|
|
for (int i = 0; i < C4NUM; i++) {
|
|
|
|
|
|
|
|
tmp_sum_value[i] += src_ic[i * input_channel];
|
|
|
|
|
|
|
|
pack_ic[i * C4NUM] = src_ic[i * input_channel];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
src_ic += 1;
|
|
|
|
|
|
|
|
pack_ic += 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int ici = input_channel; ici < ic4; ici += 1) {
|
|
|
|
|
|
|
|
for (int i = 0; i < C4NUM; i++) {
|
|
|
|
|
|
|
|
pack_ic[i * C4NUM] = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
pack_ic += 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < C4NUM; i++) {
|
|
|
|
|
|
|
|
input_sum_r[i] = tmp_sum_value[i] * filter_zp;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
src_r += input_channel * C4NUM;
|
|
|
|
|
|
|
|
pack_r += ic4 * C4NUM;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (hw_4div != plane_size) {
|
|
|
|
|
|
|
|
memset(pack_r, 0, C4NUM * ic4);
|
|
|
|
|
|
|
|
for (int hwi = hw_4div; hwi < plane_size; hwi += 1) {
|
|
|
|
|
|
|
|
int32_t tmp_sum_value = 0;
|
|
|
|
|
|
|
|
const int8_t *src_ic = src_r;
|
|
|
|
|
|
|
|
int8_t *pack_ic = pack_r;
|
|
|
|
|
|
|
|
for (int ici = 0; ici < ic_4div; ici += C4NUM) {
|
|
|
|
|
|
|
|
tmp_sum_value += src_ic[0];
|
|
|
|
|
|
|
|
tmp_sum_value += src_ic[1];
|
|
|
|
|
|
|
|
tmp_sum_value += src_ic[2];
|
|
|
|
|
|
|
|
tmp_sum_value += src_ic[3];
|
|
|
|
|
|
|
|
pack_ic[0] = src_ic[0];
|
|
|
|
|
|
|
|
pack_ic[1] = src_ic[1];
|
|
|
|
|
|
|
|
pack_ic[2] = src_ic[2];
|
|
|
|
|
|
|
|
pack_ic[3] = src_ic[3];
|
|
|
|
|
|
|
|
src_ic += C4NUM;
|
|
|
|
|
|
|
|
pack_ic += C4NUM * C4NUM;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int ici = ic_4div; ici < input_channel; ici += 1) {
|
|
|
|
|
|
|
|
tmp_sum_value += src_ic[0];
|
|
|
|
|
|
|
|
pack_ic[0] = src_ic[0];
|
|
|
|
|
|
|
|
src_ic += 1;
|
|
|
|
|
|
|
|
pack_ic += 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
input_sum[hwi] = tmp_sum_value * filter_zp;
|
|
|
|
|
|
|
|
src_r += input_channel;
|
|
|
|
|
|
|
|
pack_r += C4NUM;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int hwi = plane_size; hwi < hw4; hwi++) {
|
|
|
|
|
|
|
|
input_sum[hwi] = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RowMajor2Col16x4MajorInt8(int8_t *src, int row, int col, int8_t *dst) {
|
|
|
|
void RowMajor2Col16x4MajorInt8(int8_t *src, int row, int col, int8_t *dst) {
|
|
|
|
int row_16 = UP_ROUND(row, C16NUM);
|
|
|
|
int row_16 = UP_ROUND(row, C16NUM);
|
|
|
|
int stride = sizeof(int8_t) * 16 * 4;
|
|
|
|
int stride = sizeof(int8_t) * 16 * 4;
|
|
|
|