/**
* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "kernel_operator.h"
#include "../../../../include/common/common.h"
#include "../../../../include/common/common_func.h"
#include "../../../../include/common/simd.h"
#include "../../../../include/common/iterator.h"
#include "../../../../include/common/mma.h"
#include "../../../../include/common/utils.h"
// 将(16, row_num) 或者(row_num_padding, 16) 转置,配合UB存放的指针数据来使用
__aicore__ __inline__ __attribute__((overloadable, always_inline)) void transpose_matrix(__ubuf__ uint16_t *output_buf,
__ubuf__ uint16_t *input_buf,
uint8_t repeat_num,
int32_t dstStride = 16,
int32_t srcStride = 16)
{
vld_va_reg(VA0, (__ubuf__ uint64_t *)input_buf, L128);
vld_va_reg(VA1, (__ubuf__ uint64_t *)input_buf, H128);
vld_va_reg(VA2, (__ubuf__ uint64_t *)(output_buf), L128);
vld_va_reg(VA3, (__ubuf__ uint64_t *)(output_buf), H128);
PIPE_BARRIER(V);
scatter_vnchwconv_b16(VA2, VA0, repeat_num, dstStride, srcStride);
}
__aicore__ __inline__ __attribute__((overloadable, always_inline)) void complex_split_RI_tile_zN(
__gm__ float *__restrict__ gm_input, __gm__ float *__restrict__ gm_output, __gm__ float *__restrict__ gm_auxil,
int64_t batchSize, int64_t N1, int64_t N2, int64_t N2_padding, int32_t tile_K0, int32_t tile_N0, int32_t step_len)
{
// 除0整改
if (tile_N0 == 0) {
tile_N0 = 1;
}
const int64_t N1_round = ROUND(N1, C0_SIZE);
const int64_t N2_round = ROUND(N2, C0_SIZE);
const int16_t aic_id = get_block_idx();
const int16_t aiv_id_per_group = AscendC::GetSubBlockIdx();
const int16_t group_num = AscendC::GetBlockNum();
const int16_t subgroup_num = get_subblockdim();
const int16_t aiv_id = aic_id * subgroup_num + aiv_id_per_group;
const int16_t aiv_num = group_num * subgroup_num;
const int32_t max_num = 24 * 1024 / sizeof(float);
AscendC::GlobalTensor<float> gm_input_tensor, gm_output_tensor;
AsdopsBuffer<ArchType::ASCEND_V220> buf;
gm_input_tensor.SetGlobalBuffer(reinterpret_cast<__gm__ float *>(gm_input));
gm_output_tensor.SetGlobalBuffer(reinterpret_cast<__gm__ float *>(gm_output));
int32_t now_UB = 0;
auto buf1_input = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf1_input_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf1_output_real = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf1_output_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_input = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_input_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_output_real = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_output_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
int32_t N2_max_num = max_num;
int32_t N1_max_num = N2_max_num / ROUND(N2, tile_N0);
N1_max_num = N1_max_num + (N1_max_num == 0);
int32_t batch_max_num;
N1_max_num = MIN(N1_max_num, N1);
// 除0整改
if (N1_max_num == 0) {
N1_max_num = 1;
}
N2_max_num = MIN(N2_max_num, ROUND(N2, tile_N0));
// 除0整改
if (N2_max_num == 0) {
N2_max_num = 1;
}
batch_max_num = max_num / (N1_max_num * N2_max_num);
batch_max_num += (batch_max_num == 0);
int64_t N1_loop = (N1 + N1_max_num - 1) / N1_max_num;
// 除0整改
if (N1_loop == 0) {
N1_loop = 1;
}
int64_t N2_loop = (N2 + N2_max_num - 1) / N2_max_num;
// 除0整改
if (N2_loop == 0) {
N2_loop = 1;
}
const int64_t batch_loop = (batchSize + batch_max_num - 1) / batch_max_num;
const int64_t batch_remain = batchSize % batch_max_num;
const int64_t N2_remain = N2 % N2_max_num;
const int64_t N1_remain = N1 % N1_max_num;
const int64_t loop = batch_loop * N1_loop * N2_loop;
bool flag = 1;
SET_FLAG(MTE3, MTE2, EVENT_ID0);
SET_FLAG(MTE3, MTE2, EVENT_ID1);
for (int64_t i = 0; i < loop; i++) {
int64_t loop_idx = i;
if (loop_idx % static_cast<int64_t>(aiv_num) != static_cast<int64_t>(aiv_id)) {
continue;
}
int64_t N2_block_idx = loop_idx % N2_loop;
int64_t batch_N1_idx = loop_idx / N2_loop;
int64_t N1_idx = batch_N1_idx % N1_loop;
int64_t batch_idx = batch_N1_idx / N1_loop;
int32_t N2_actual = N2_max_num;
if (N2_block_idx == N2_loop - 1 && N2_remain > 0) {
N2_actual = N2_remain;
}
int32_t N1_actual = N1_max_num;
if (N1_idx == N1_loop - 1 && N1_remain > 0) {
N1_actual = N1_remain;
}
int32_t batch_actual = batch_max_num;
if (batch_idx == batch_loop - 1 && batch_remain > 0) {
batch_actual = batch_remain;
}
int32_t N2_actual_round = ROUND(N2_actual, tile_N0);
auto buf_input = flag ? buf1_input : buf2_input;
auto buf_input_imag = flag ? buf1_input_imag : buf2_input_imag;
auto buf_output_real = flag ? buf1_output_real : buf2_output_real;
auto buf_output_imag = flag ? buf1_output_imag : buf2_output_imag;
auto event_id = flag ? EVENT_ID0 : EVENT_ID1;
WAIT_FLAG(MTE3, MTE2, event_id);
// 按照不同shape来合并访存
if (N1_actual == N1 && N2_actual == N2 && N2 <= tile_N0) {
const int64_t data_input_index =
batch_idx * batch_max_num * N1 * N2 + N1_idx * N1_max_num * N2 + N2_block_idx * N2_max_num;
copy_gm2ubuf(buf_input, gm_input_tensor[data_input_index * 2], batch_actual * N1_actual, ROUND(2 * N2_actual, 8), 2 * N2,
2 * N2_actual_round);
SET_FLAG(MTE2, V, event_id);
WAIT_FLAG(MTE2, V, event_id);
const int64_t data_output_index = batch_idx * batch_max_num * 2 * N1 * N2_padding +
N1_idx * N1_max_num * tile_N0 + N2_block_idx * 2 * N1 * N2_max_num;
vreducev2(reinterpret_cast<__ubuf__ uint32_t *>(buf_output_real.GetPhyAddr()),
reinterpret_cast<__ubuf__ uint32_t *>(buf_input.GetPhyAddr()), nullptr,
(batch_actual * N1_actual * 2 * N2_actual_round + 8 * C0_SIZE - 1) / (8 * C0_SIZE), 1, 1, 8, 8);
vreducev2(reinterpret_cast<__ubuf__ uint32_t *>(buf_output_imag.GetPhyAddr()),
reinterpret_cast<__ubuf__ uint32_t *>(buf_input.GetPhyAddr()), nullptr,
(batch_actual * N1_actual * 2 * N2_actual_round + 8 * C0_SIZE - 1) / (8 * C0_SIZE), 1, 2, 8, 8);
PIPE_BARRIER(V);
AscendC::DataCopy(buf_input, buf_output_real,
AscendC::DataCopyParams(
batch_actual,
N1_actual * N2_actual_round / C0_SIZE,
0,
(2 * N1_actual * N2_actual_round - N1_actual * N2_actual_round) / C0_SIZE
)
);
AscendC::DataCopy(buf_input[N1_actual * N2_actual_round], buf_output_imag,
AscendC::DataCopyParams(
batch_actual,
N1_actual * N2_actual_round / C0_SIZE,
0,
(2 * N1_actual * N2_actual_round - N1_actual * N2_actual_round) / C0_SIZE
)
);
SET_FLAG(V, MTE3, event_id);
WAIT_FLAG(V, MTE3, event_id);
copy_ubuf2gm(gm_output_tensor[data_output_index], buf_input, batch_actual, 2 * N1_actual * tile_N0, 2 * N1_actual * tile_N0,
2 * N1 * tile_N0);
} else if (batch_max_num == 1 && N2_actual == N2 && N2 <= tile_N0) {
const int64_t data_input_index =
batch_idx * batch_max_num * N1 * N2 + N1_idx * N1_max_num * N2 + N2_block_idx * N2_max_num;
copy_gm2ubuf(buf_input, gm_input_tensor[data_input_index * 2], batch_actual * N1_actual, ROUND(2 * N2_actual, 8), 2 * N2,
2 * N2_actual_round);
SET_FLAG(MTE2, V, event_id);
WAIT_FLAG(MTE2, V, event_id);
const int64_t data_output_index = batch_idx * batch_max_num * 2 * N1 * N2_padding +
N1_idx * N1_max_num * tile_N0 + N2_block_idx * 2 * N1 * N2_max_num;
vreducev2(reinterpret_cast<__ubuf__ uint32_t *>(buf_output_real.GetPhyAddr()),
reinterpret_cast<__ubuf__ uint32_t *>(buf_input.GetPhyAddr()), nullptr,
(batch_actual * N1_actual * 2 * N2_actual_round + 8 * C0_SIZE - 1) / (8 * C0_SIZE), 1, 1, 8, 8);
SET_FLAG(V, MTE3, event_id);
vreducev2(reinterpret_cast<__ubuf__ uint32_t *>(buf_output_imag.GetPhyAddr()),
reinterpret_cast<__ubuf__ uint32_t *>(buf_input.GetPhyAddr()), nullptr,
(batch_actual * N1_actual * 2 * N2_actual_round + 8 * C0_SIZE - 1) / (8 * C0_SIZE), 1, 2, 8, 8);
SET_FLAG(V, MTE3, event_id + 2);
WAIT_FLAG(V, MTE3, event_id);
copy_ubuf2gm(gm_output_tensor[data_output_index], buf_output_real, N1_actual, tile_N0, tile_N0, tile_N0);
WAIT_FLAG(V, MTE3, event_id + 2);
copy_ubuf2gm(gm_output_tensor[data_output_index + N1 * tile_N0], buf_output_imag, N1_actual, tile_N0, tile_N0, tile_N0);
} else if (batch_max_num == 1 && N1_max_num == 1) {
const int64_t data_input_index =
batch_idx * batch_max_num * N1 * N2 + N1_idx * N1_max_num * N2 + N2_block_idx * N2_max_num;
copy_gm2ubuf(buf_input, gm_input_tensor[data_input_index * 2], batch_actual * N1_actual, ROUND(2 * N2_actual, 8), 2 * N2,
2 * N2_actual_round);
SET_FLAG(MTE2, V, event_id);
WAIT_FLAG(MTE2, V, event_id);
const int64_t data_output_index = batch_idx * batch_max_num * 2 * N1 * N2_padding +
N1_idx * N1_max_num * tile_N0 + N2_block_idx * 2 * N1 * N2_max_num;
auto gm_output_real_ptr = gm_output_tensor[data_output_index];
auto gm_output_imag_ptr = gm_output_tensor[data_output_index + N1 * tile_N0];
vreducev2(reinterpret_cast<__ubuf__ uint32_t *>(buf_output_real.GetPhyAddr()),
reinterpret_cast<__ubuf__ uint32_t *>(buf_input.GetPhyAddr()), nullptr,
(batch_actual * N1_actual * 2 * N2_actual_round + 8 * C0_SIZE - 1) / (8 * C0_SIZE), 1, 1, 8, 8);
SET_FLAG(V, MTE3, event_id);
vreducev2(reinterpret_cast<__ubuf__ uint32_t *>(buf_output_imag.GetPhyAddr()),
reinterpret_cast<__ubuf__ uint32_t *>(buf_input.GetPhyAddr()), nullptr,
(batch_actual * N1_actual * 2 * N2_actual_round + 8 * C0_SIZE - 1) / (8 * C0_SIZE), 1, 2, 8, 8);
SET_FLAG(V, MTE3, event_id + 2);
WAIT_FLAG(V, MTE3, event_id);
AscendC::DataCopyPad(gm_output_real_ptr, buf_output_real,
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - tile_N0) * sizeof(float), 0));
WAIT_FLAG(V, MTE3, event_id + 2);
AscendC::DataCopyPad(gm_output_imag_ptr, buf_output_imag,
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - tile_N0) * sizeof(float), 0));
} else {
const int64_t data_input_index =
batch_idx * batch_max_num * N1 * N2 + N1_idx * N1_max_num * N2 + N2_block_idx * N2_max_num;
copy_gm2ubuf(buf_input, gm_input_tensor[data_input_index * 2], batch_actual * N1_actual, ROUND(2 * N2_actual, 8), 2 * N2,
2 * N2_actual_round);
SET_FLAG(MTE2, V, event_id);
WAIT_FLAG(MTE2, V, event_id);
const int64_t data_output_index = batch_idx * batch_max_num * 2 * N1 * N2_padding +
N1_idx * N1_max_num * tile_N0 + N2_block_idx * 2 * N1 * N2_max_num;
auto gm_output_real_ptr = gm_output_tensor[data_output_index];
auto gm_output_imag_ptr = gm_output_tensor[data_output_index + N1 * tile_N0];
vreducev2(reinterpret_cast<__ubuf__ uint32_t *>(buf_output_real.GetPhyAddr()),
reinterpret_cast<__ubuf__ uint32_t *>(buf_input.GetPhyAddr()), nullptr,
(batch_actual * N1_actual * 2 * N2_actual_round + 8 * C0_SIZE - 1) / (8 * C0_SIZE), 1, 1, 8, 8);
vreducev2(reinterpret_cast<__ubuf__ uint32_t *>(buf_output_imag.GetPhyAddr()),
reinterpret_cast<__ubuf__ uint32_t *>(buf_input.GetPhyAddr()), nullptr,
(batch_actual * N1_actual * 2 * N2_actual_round + 8 * C0_SIZE - 1) / (8 * C0_SIZE), 1, 2, 8, 8);
PIPE_BARRIER(V);
for (int32_t j = 0; j < batch_actual; j++) {
for (int32_t i = 0; i < N1_actual; i++) {
AscendC::DataCopy(buf_input[j * 2 * N1_actual * N2_actual_round + i * tile_N0],
buf_output_real[j * N1_actual * N2_actual_round + i * N2_actual_round],
AscendC::DataCopyParams(
N2_actual_round / tile_N0,
tile_N0 / C0_SIZE,
0,
(N1_actual * tile_N0 - tile_N0) / C0_SIZE
)
);
AscendC::DataCopy(buf_input[j * 2 * N1_actual * N2_actual_round + N1_actual * N2_actual_round + i * tile_N0],
buf_output_imag[j * N1_actual * N2_actual_round + i * N2_actual_round],
AscendC::DataCopyParams(
N2_actual_round / tile_N0,
tile_N0 / C0_SIZE,
0,
(N1_actual * tile_N0 - tile_N0) / C0_SIZE
)
);
}
}
SET_FLAG(V, MTE3, event_id);
WAIT_FLAG(V, MTE3, event_id);
for (int32_t j = 0; j < batch_actual; j++) {
AscendC::DataCopyPad(gm_output_real_ptr[j * 2 * N1 * N2_padding], buf_input[j * 2 * N1_actual * N2_actual_round],
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, N1_actual * tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - N1_actual * tile_N0) * sizeof(float), 0));
AscendC::DataCopyPad(gm_output_imag_ptr[j * 2 * N1 * N2_padding],
buf_input[j * 2 * N1_actual * N2_actual_round + N1_actual * N2_actual_round],
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, N1_actual * tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - N1_actual * tile_N0) * sizeof(float), 0));
}
}
SET_FLAG(MTE3, MTE2, event_id);
flag = 1 - flag;
}
WAIT_FLAG(MTE3, MTE2, EVENT_ID0);
WAIT_FLAG(MTE3, MTE2, EVENT_ID1);
}
__aicore__ __inline__ __attribute__((overloadable, always_inline)) void c2r_even_complex_split_RI_tile_zN(
__gm__ float * __restrict__ gm_input_real,
__gm__ float * __restrict__ gm_input_imag,
__gm__ float * __restrict__ gm_output,
__gm__ float * __restrict__ gm_auxil,
int64_t batchSize,
int32_t N1,
int64_t N2,
int64_t N2_padding,
int32_t tile_K0,
int32_t tile_N0,
int32_t step_len
) {
const int32_t N1_round = ROUND(N1, C0_SIZE);
const int64_t N2_round = ROUND(N2, C0_SIZE);
const int16_t aic_id = get_block_idx();
const int16_t aiv_id_per_group = AscendC::GetSubBlockIdx();
const int16_t group_num = AscendC::GetBlockNum();
const int16_t subgroup_num = get_subblockdim();
const int16_t aiv_id = aic_id * subgroup_num + aiv_id_per_group;
const int16_t aiv_num = group_num * subgroup_num;
const int32_t max_num = 24 * 1024 / sizeof(float);
AscendC::GlobalTensor<float> gm_input_real_tensor, gm_output_tensor, gm_input_imag_tensor;
gm_input_real_tensor.SetGlobalBuffer(reinterpret_cast<__gm__ float *>(gm_input_real));
gm_input_imag_tensor.SetGlobalBuffer(reinterpret_cast<__gm__ float *>(gm_input_imag));
gm_output_tensor.SetGlobalBuffer(reinterpret_cast<__gm__ float *>(gm_output));
int32_t now_UB = 0;
AsdopsBuffer<ArchType::ASCEND_V220> buf;
auto buf1_input = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf1_input_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf1_output_real = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf1_output_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_input = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_input_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_output_real = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_output_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
int32_t N2_max_num = max_num;
int32_t N1_max_num = N2_max_num / ROUND(N2, tile_N0);
N1_max_num = N1_max_num + (N1_max_num == 0);
int32_t batch_max_num;
N1_max_num = MIN(N1_max_num, N1);
N2_max_num = MIN(N2_max_num, ROUND(N2, tile_N0));
batch_max_num = max_num / (N1_max_num * N2_max_num);
batch_max_num += (batch_max_num == 0);
const int32_t N1_loop = (N1 + N1_max_num - 1) / N1_max_num;
const int64_t N2_loop = (N2 + N2_max_num - 1) / N2_max_num;
const int64_t batch_loop = (batchSize + batch_max_num - 1) / batch_max_num;
const int64_t batch_remain = batchSize % batch_max_num;
const int64_t N2_remain = N2 % N2_max_num;
const int32_t N1_remain = N1 % N1_max_num;
const int64_t loop = batch_loop * N1_loop * N2_loop;
bool flag = 1;
SET_FLAG(MTE3, MTE2, EVENT_ID0);
SET_FLAG(MTE3, MTE2, EVENT_ID1);
for (int64_t i = 0; i < loop; i++) {
int64_t loop_idx = i;
if (loop_idx % aiv_num != aiv_id) {
continue;
}
int64_t N2_block_idx = loop_idx % N2_loop;
int64_t batch_N1_idx = loop_idx / N2_loop;
int32_t N1_idx = batch_N1_idx % N1_loop;
int64_t batch_idx = batch_N1_idx / N1_loop;
int32_t N2_actual = N2_max_num;
if (N2_block_idx == N2_loop - 1 && N2_remain > 0) {
N2_actual = N2_remain;
}
int32_t N1_actual = N1_max_num;
if (N1_idx == N1_loop - 1 && N1_remain > 0) {
N1_actual = N1_remain;
}
int32_t batch_actual = batch_max_num;
if (batch_idx == batch_loop - 1 && batch_remain > 0) {
batch_actual = batch_remain;
}
int32_t N2_actual_round = ROUND(N2_actual, tile_N0);
auto buf_input = flag ? buf1_input : buf2_input;
auto buf_input_imag = flag ? buf1_input_imag : buf2_input_imag;
auto buf_output_real = flag ? buf1_output_real : buf2_output_real;
auto buf_output_imag = flag ? buf1_output_imag : buf2_output_imag;
auto event_id = flag ? EVENT_ID0 : EVENT_ID1;
WAIT_FLAG(MTE3, MTE2, event_id);
const int64_t data_input_index = batch_idx * batch_max_num * N1 * N2 + N1_idx * N1_max_num * N2 + N2_block_idx * N2_max_num;
copy_gm2ubuf(buf_output_real, gm_input_real_tensor[data_input_index], batch_actual * N1_actual, ROUND(N2_actual, 8), N2, N2_actual_round);
copy_gm2ubuf(buf_output_imag, gm_input_imag_tensor[data_input_index], batch_actual * N1_actual, ROUND(N2_actual, 8), N2, N2_actual_round);
SET_FLAG(MTE2, V, event_id);
WAIT_FLAG(MTE2, V, event_id);
// compute output index
const int64_t data_output_index = batch_idx * batch_max_num * 2 * N1 * N2_padding + N1_idx * N1_max_num * tile_N0 + N2_block_idx * 2 * N1 * N2_max_num;
auto gm_current_output_real = gm_output_tensor[data_output_index];
auto gm_current_output_imag = gm_output_tensor[data_output_index + N1 * tile_N0];
// 按照不同shape来合并访存
if (N1_actual == N1 && N2_actual == N2 && N2 <= tile_N0) {
AscendC::DataCopy(buf_input, buf_output_real,
AscendC::DataCopyParams(
batch_actual,
N1_actual * N2_actual_round / C0_SIZE,
0,
(2 * N1_actual * N2_actual_round - N1_actual * N2_actual_round) / C0_SIZE
)
);
AscendC::DataCopy(buf_input[N1_actual * N2_actual_round], buf_output_imag,
AscendC::DataCopyParams(
batch_actual,
N1_actual * N2_actual_round / C0_SIZE,
0,
(2 * N1_actual * N2_actual_round - N1_actual * N2_actual_round) / C0_SIZE
)
);
SET_FLAG(V, MTE3, event_id);
WAIT_FLAG(V, MTE3, event_id);
copy_ubuf2gm(gm_current_output_real, buf_input, batch_actual, 2 * N1_actual * tile_N0, 2 * N1_actual * tile_N0, 2 * N1 * tile_N0);
} else if (batch_max_num == 1 && N2_actual == N2 && N2 <= tile_N0) {
SET_FLAG(V, MTE3, event_id);
SET_FLAG(V, MTE3, event_id + 2);
WAIT_FLAG(V, MTE3, event_id);
copy_ubuf2gm(gm_current_output_real, buf_output_real, N1_actual, tile_N0, tile_N0, tile_N0);
WAIT_FLAG(V, MTE3, event_id + 2);
copy_ubuf2gm(gm_current_output_imag, buf_output_imag, N1_actual, tile_N0, tile_N0, tile_N0);
} else if (batch_max_num == 1 && N1_max_num == 1) {
SET_FLAG(V, MTE3, event_id);
SET_FLAG(V, MTE3, event_id + 2);
WAIT_FLAG(V, MTE3, event_id);
AscendC::DataCopyPad(gm_current_output_real, buf_output_real,
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - tile_N0) * sizeof(float), 0));
WAIT_FLAG(V, MTE3, event_id + 2);
AscendC::DataCopyPad(gm_current_output_imag, buf_output_imag,
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - tile_N0) * sizeof(float), 0));
} else {
for (int j = 0; j < batch_actual; j++) {
for (int i = 0; i < N1_actual; i++) {
AscendC::DataCopy(buf_input[j * 2 * N1_actual * N2_actual_round + i * tile_N0],
buf_output_real[j * N1_actual * N2_actual_round + i * N2_actual_round],
AscendC::DataCopyParams(
N2_actual_round / tile_N0,
tile_N0 / C0_SIZE,
0,
(N1_actual * tile_N0 - tile_N0) / C0_SIZE
)
);
AscendC::DataCopy(buf_input[j * 2 * N1_actual * N2_actual_round + N1_actual * N2_actual_round + i * tile_N0],
buf_output_imag[j * N1_actual * N2_actual_round + i * N2_actual_round],
AscendC::DataCopyParams(
N2_actual_round / tile_N0,
tile_N0 / C0_SIZE,
0,
(N1_actual * tile_N0 - tile_N0) / C0_SIZE
)
);
}
}
SET_FLAG(V, MTE3, event_id);
WAIT_FLAG(V, MTE3, event_id);
for (int j = 0; j < batch_actual; j++) {
AscendC::DataCopyPad(gm_current_output_real[j * 2 * N1 * N2_padding],
buf_input[j * 2 * N1_actual * N2_actual_round],
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, N1_actual * tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - N1_actual * tile_N0) * sizeof(float), 0));
AscendC::DataCopyPad(gm_current_output_imag[j * 2 * N1 * N2_padding],
buf_input[j * 2 * N1_actual * N2_actual_round + N1_actual * N2_actual_round],
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, N1_actual * tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - N1_actual * tile_N0) * sizeof(float), 0));
}
}
SET_FLAG(MTE3, MTE2, event_id);
flag = 1 - flag;
}
WAIT_FLAG(MTE3, MTE2, EVENT_ID0);
WAIT_FLAG(MTE3, MTE2, EVENT_ID1);
}
// 对于 N2 较小的情况, 一次读取多个 N2, 在UB中填充成ROUND(N2, tile_N0)。并存入到全局内存
__aicore__ __inline__ __attribute__((overloadable, always_inline)) void complex_split_RI_tile_zN_vtranspose_load(
__gm__ float *__restrict__ gm_input, __gm__ float *__restrict__ gm_output, __gm__ float *__restrict__ gm_auxil,
int64_t batchSize, int64_t N1, int64_t N2, int64_t N2_padding, int32_t tile_K0, int32_t tile_N0, int32_t step_len)
{
// 除0整改
if (N2 == 0) {
N2 = 1;
}
const int64_t N1_round = ROUND(N1, C0_SIZE);
const int64_t N2_round = ROUND(N2, C0_SIZE);
const int16_t aic_id = get_block_idx();
const int16_t aiv_id_per_group = AscendC::GetSubBlockIdx();
const int16_t group_num = AscendC::GetBlockNum();
const int16_t subgroup_num = get_subblockdim();
const int16_t aiv_id = aic_id * subgroup_num + aiv_id_per_group;
const int16_t aiv_num = group_num * subgroup_num;
AscendC::GlobalTensor<float> gm_input_tensor, gm_output_tensor;
gm_input_tensor.SetGlobalBuffer(reinterpret_cast<__gm__ float *>(gm_input));
gm_output_tensor.SetGlobalBuffer(reinterpret_cast<__gm__ float *>(gm_output));
// 最大空间
const int32_t max_num = 23 * 1024 / sizeof(float);
int32_t now_UB = 0;
AsdopsBuffer<ArchType::ASCEND_V220> buf;
// addr_buf 存放 scatter_vnchwconv_b16 需要的指针数组
auto buf1_input_transpose1_addr_buf = buf.GetBuffer<BufferType::ASCEND_UB, uint16_t>((uintptr_t)now_UB);
now_UB += 64;
auto buf1_output_real_transpose1_addr_buf = buf.GetBuffer<BufferType::ASCEND_UB, uint16_t>((uintptr_t)now_UB);
now_UB += 64;
auto buf1_input_transpose2_addr_buf = buf.GetBuffer<BufferType::ASCEND_UB, uint16_t>((uintptr_t)now_UB);
now_UB += 64;
auto buf1_output_real_transpose2_addr_buf = buf.GetBuffer<BufferType::ASCEND_UB, uint16_t>((uintptr_t)now_UB);
now_UB += 64;
auto buf2_input_transpose1_addr_buf = buf.GetBuffer<BufferType::ASCEND_UB, uint16_t>((uintptr_t)now_UB);
now_UB += 64;
auto buf2_output_real_transpose1_addr_buf = buf.GetBuffer<BufferType::ASCEND_UB, uint16_t>((uintptr_t)now_UB);
now_UB += 64;
auto buf2_input_transpose2_addr_buf = buf.GetBuffer<BufferType::ASCEND_UB, uint16_t>((uintptr_t)now_UB);
now_UB += 64;
auto buf2_output_real_transpose2_addr_buf = buf.GetBuffer<BufferType::ASCEND_UB, uint16_t>((uintptr_t)now_UB);
now_UB += 64;
auto buf1_input = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf1_input_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
now_UB += C0_SIZE * 16 * sizeof(float);
auto buf1_output_real = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf1_output_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
now_UB += C0_SIZE * 16 * sizeof(float);
auto buf2_input = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_input_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
now_UB += C0_SIZE * 16 * sizeof(float);
auto buf2_output_real = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_output_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
now_UB += C0_SIZE * 16 * sizeof(float);
int32_t N2_max_num = max_num;
int32_t N1_max_num = N2_max_num / ROUND(N2, tile_N0);
N1_max_num = N1_max_num + (N1_max_num == 0);
int32_t batch_max_num;
N1_max_num = MIN(N1_max_num, N1);
// 除0整改
if (N1_max_num == 0) {
N1_max_num = 1;
}
N2_max_num = MIN(N2_max_num, ROUND(N2, tile_N0));
// 除0整改
if (N2_max_num == 0) {
N2_max_num = 1;
}
batch_max_num = max_num / (N1_max_num * N2_max_num);
batch_max_num += (batch_max_num == 0);
// 控制实部和虚部空间一起能读入8 * 16 个tile_N0, 这里默认 N2 < tile_N0
if (N1_max_num == N1 && N2 <= tile_N0 && batch_max_num * N1_max_num >= 8 * C0_SIZE) {
batch_max_num = batch_max_num * N1_max_num / (8 * C0_SIZE) * (8 * C0_SIZE) / N1_max_num;
}
// 如果读取的N2多于8 * 16 个,希望行宽尽量大。行数为16行。
int32_t row_num = (2 * batch_max_num * N1_max_num + 16 * C0_SIZE - 1) / (16 * C0_SIZE) * C0_SIZE * N2;
int32_t row_num_padding = (row_num / N2 * tile_N0);
// 通过数据搬运和vector来减少scalar,下面的代码和上面注释的代码功能相同
for (int32_t i = 0; i < 16; i++) {
buf1_output_real_transpose1_addr_buf.SetValue(i, (uint16_t)(i));
}
SET_FLAG(S, V, EVENT_ID0);
WAIT_FLAG(S, V, EVENT_ID0);
AscendC::SetMaskCount();
AscendC::SetVectorMask<int16_t>(0, 16);
muls_v<ArchType::ASCEND_V220, int16_t>(buf1_input_transpose1_addr_buf.ReinterpretCast<int16_t>(),
buf1_output_real_transpose1_addr_buf.ReinterpretCast<int16_t>(),
row_num / C0_SIZE, 1, 1, 1, 8, 8);
muls_v<ArchType::ASCEND_V220, int16_t>(buf1_output_real_transpose2_addr_buf.ReinterpretCast<int16_t>(),
buf1_output_real_transpose1_addr_buf.ReinterpretCast<int16_t>(),
(row_num_padding + C0_SIZE) / C0_SIZE, 1, 1, 1, 8, 8);
AscendC::DataCopy(buf1_input_transpose2_addr_buf,
buf1_output_real_transpose1_addr_buf,
AscendC::DataCopyParams(
1,
16 / C0_SIZE,
0,
0
)
);
PIPE_BARRIER(V);
adds_v<ArchType::ASCEND_V220, int16_t>(buf1_input_transpose1_addr_buf.ReinterpretCast<int16_t>(),
buf1_input_transpose1_addr_buf.ReinterpretCast<int16_t>(),
(reinterpret_cast<uintptr_t>(buf1_input.GetPhyAddr())) / 4 / 8,
1, 1, 1, 8, 8);
adds_v<ArchType::ASCEND_V220, int16_t>(buf1_output_real_transpose1_addr_buf.ReinterpretCast<int16_t>(),
buf1_output_real_transpose1_addr_buf.ReinterpretCast<int16_t>(),
(reinterpret_cast<uintptr_t>(buf1_output_real.GetPhyAddr())) / 4 / 8,
1, 1, 1, 8, 8);
adds_v<ArchType::ASCEND_V220, int16_t>(buf1_input_transpose2_addr_buf.ReinterpretCast<int16_t>(),
buf1_input_transpose2_addr_buf.ReinterpretCast<int16_t>(),
(reinterpret_cast<uintptr_t>(buf1_input.GetPhyAddr())) / 4 / 8,
1, 1, 1, 8, 8);
adds_v<ArchType::ASCEND_V220, int16_t>(buf1_output_real_transpose2_addr_buf.ReinterpretCast<int16_t>(),
buf1_output_real_transpose2_addr_buf.ReinterpretCast<int16_t>(),
(reinterpret_cast<uintptr_t>(buf1_output_real.GetPhyAddr())) / 4 / 8,
1, 1, 1, 8, 8);
AscendC::SetMaskNorm();
AscendC::SetVectorMask<int16_t>((uint64_t)-1, (uint64_t)-1);
PIPE_BARRIER(V);
adds_v<ArchType::ASCEND_V220, int16_t>(buf2_input_transpose1_addr_buf.ReinterpretCast<int16_t>(),
buf1_input_transpose1_addr_buf.ReinterpretCast<int16_t>(),
(reinterpret_cast<uintptr_t>(buf2_input.GetPhyAddr())
- reinterpret_cast<uintptr_t>(buf1_input.GetPhyAddr())) / 4 / 8,
1, 1, 1, 8, 8);
PIPE_BARRIER(V);
const int64_t N1_loop = (N1 + N1_max_num - 1) / N1_max_num;
const int64_t N2_loop = (N2 + N2_max_num - 1) / N2_max_num;
const int64_t batch_loop = (batchSize + batch_max_num - 1) / batch_max_num;
const int64_t batch_remain = batchSize % batch_max_num;
const int64_t N2_remain = N2 % N2_max_num;
const int64_t N1_remain = N1 % N1_max_num;
const int64_t loop = batch_loop * N1_loop * N2_loop;
bool flag = 1;
SET_FLAG(MTE3, MTE2, EVENT_ID0);
SET_FLAG(MTE3, MTE2, EVENT_ID1);
for (int64_t i = 0; i < loop; i++) {
int64_t loop_idx = i;
if (loop_idx % static_cast<int64_t>(aiv_num) != static_cast<int64_t>(aiv_id)) {
continue;
}
int64_t N2_block_idx = loop_idx % N2_loop;
int64_t batch_N1_idx = loop_idx / N2_loop;
int64_t N1_idx = batch_N1_idx % N1_loop;
int64_t batch_idx = batch_N1_idx / N1_loop;
int32_t N2_actual = N2_max_num;
if (N2_block_idx == N2_loop - 1 && N2_remain > 0) {
N2_actual = N2_remain;
}
int32_t N1_actual = N1_max_num;
if (N1_idx == N1_loop - 1 && N1_remain > 0) {
N1_actual = N1_remain;
}
int32_t batch_actual = batch_max_num;
if (batch_idx == batch_loop - 1 && batch_remain > 0) {
batch_actual = batch_remain;
}
int32_t N2_actual_round = ROUND(N2_actual, tile_N0);
auto buf_input = flag ? buf1_input : buf2_input;
auto buf_input_imag = flag ? buf1_input_imag : buf2_input_imag;
auto buf_output_real = flag ? buf1_output_real : buf2_output_real;
auto buf_output_imag = flag ? buf1_output_imag : buf2_output_imag;
auto event_id = flag ? EVENT_ID0 : EVENT_ID1;
auto buf_input_transpose1_addr_buf = flag ? buf1_input_transpose1_addr_buf : buf2_input_transpose1_addr_buf;
auto buf_output_real_transpose1_addr_buf = flag ? buf1_output_real_transpose1_addr_buf :
buf2_output_real_transpose1_addr_buf;
auto buf_input_transpose2_addr_buf = flag ? buf1_input_transpose2_addr_buf : buf2_input_transpose2_addr_buf;
auto buf_output_real_transpose2_addr_buf = flag ? buf1_output_real_transpose2_addr_buf :
buf2_output_real_transpose2_addr_buf;
WAIT_FLAG(MTE3, MTE2, event_id);
const int64_t data_input_index =
batch_idx * batch_max_num * N1 * N2 + N1_idx * N1_max_num * N2 + N2_block_idx * N2_max_num;
// 读取未对齐的数据
copy_gm2ubuf(buf_input, gm_input_tensor[data_input_index * 2], 1, batch_actual * N1 * 2 * N2, ROUND(batch_actual * N1 * 2 * N2, 8),
ROUND(batch_actual * N1 * 2 * N2, 8));
SET_FLAG(MTE2, V, event_id);
WAIT_FLAG(MTE2, V, event_id);
const int64_t data_output_index = batch_idx * batch_max_num * 2 * N1 * N2_padding +
N1_idx * N1_max_num * tile_N0 + N2_block_idx * 2 * N1 * N2_max_num;
vreducev2(reinterpret_cast<__ubuf__ uint32_t *>(buf_output_real.GetPhyAddr()),
reinterpret_cast<__ubuf__ uint32_t *>(buf_input.GetPhyAddr()), nullptr,
(batch_actual * N1 * 2 * N2 + 8 * C0_SIZE - 1) / (8 * C0_SIZE), 1, 1, 8, 8);
// 将虚部放在实部后面,并且要能将实部和虚部取出来。故放的位置需要32B对齐。
vreducev2(reinterpret_cast<__ubuf__ uint32_t *>(buf_output_real[ROUND(batch_actual * N1 * N2, 8 * N2)].GetPhyAddr()),
reinterpret_cast<__ubuf__ uint32_t *>(buf_input.GetPhyAddr()), nullptr,
(batch_actual * N1 * 2 * N2 + 8 * C0_SIZE - 1) / (8 * C0_SIZE), 1, 2, 8, 8);
PIPE_BARRIER(V);
AscendC::DataCopy(buf_input,
buf_output_real,
AscendC::DataCopyParams(
1,
2 * ROUND(batch_actual * N1 * N2, 8 * N2) / C0_SIZE,
0,
0
)
);
PIPE_BARRIER(V);
// 矩阵转置 (16, row_num) -> (row_num, 16)
transpose_matrix(reinterpret_cast<__ubuf__ uint16_t *>(buf_output_real_transpose1_addr_buf.GetPhyAddr()),
reinterpret_cast<__ubuf__ uint16_t *>(buf_input_transpose1_addr_buf.GetPhyAddr()),
(16 * row_num / (8 * 16)), 16, 1);
PIPE_BARRIER(V);
AscendC::Duplicate<float>(buf_input, 0.0, 2 * max_num + 16 * C0_SIZE);
PIPE_BARRIER(V);
// 数据搬运 (row_num, 16) -> (row_num_padding + C0_SIZE, 16)
AscendC::DataCopy(buf_input,
buf_output_real,
AscendC::DataCopyParams(
row_num / N2,
N2 * 16 / C0_SIZE,
0,
(tile_N0 * 16 - N2 * 16) / C0_SIZE
)
);
PIPE_BARRIER(V);
// 矩阵转置 (row_num_padding + C0_SIZE, 16) -> (16, row_num_padding + C0_SIZE)
transpose_matrix(reinterpret_cast<__ubuf__ uint16_t *>(buf_output_real_transpose2_addr_buf.GetPhyAddr()),
reinterpret_cast<__ubuf__ uint16_t *>(buf_input_transpose2_addr_buf.GetPhyAddr()),
16 * (row_num_padding + C0_SIZE) / (8 * 16), 1, 16);
PIPE_BARRIER(V);
AscendC::DataCopy(buf_input,
buf_output_real,
AscendC::DataCopyParams(
16,
row_num_padding / C0_SIZE,
(row_num_padding + C0_SIZE - row_num_padding) / C0_SIZE,
0
)
);
PIPE_BARRIER(V);
// 合并实部和虚部的访存
AscendC::DataCopy(buf_output_real,
buf_input,
AscendC::DataCopyParams(
batch_actual,
N1 * tile_N0 / C0_SIZE,
0,
(2 * N1 * tile_N0 - N1 * tile_N0) / C0_SIZE
)
);
AscendC::DataCopy(buf_output_real[N1 * tile_N0],
buf_input[ROUND(batch_actual * N1 * tile_N0, 8 * tile_N0)],
AscendC::DataCopyParams(
batch_actual,
N1 * tile_N0 / C0_SIZE,
0,
(2 * N1 * tile_N0 - N1 * tile_N0) / C0_SIZE
)
);
SET_FLAG(V, MTE3, event_id);
WAIT_FLAG(V, MTE3, event_id);
copy_ubuf2gm(gm_output_tensor[data_output_index], buf_output_real, batch_actual, 2 * N1 * tile_N0, 2 * N1 * tile_N0,
2 * N1 * tile_N0);
SET_FLAG(MTE3, MTE2, event_id);
flag = 1 - flag;
}
WAIT_FLAG(MTE3, MTE2, EVENT_ID0);
WAIT_FLAG(MTE3, MTE2, EVENT_ID1);
}
__aicore__ __inline__ __attribute__((always_inline)) void complex_split_RI_tile_zN_odd(
__gm__ float *__restrict__ gm_input, __gm__ float *__restrict__ gm_output, __gm__ float *__restrict__ gm_auxil,
int64_t batchSize, int64_t N1, int64_t N2, int64_t N2_padding, int32_t tile_K0, int32_t tile_N0, int32_t step_len)
{
// 除0整改
if (tile_N0 == 0) {
tile_N0 = 1;
}
const int64_t N1_round = ROUND(N1, C0_SIZE);
const int64_t N2_round = ROUND(N2, C0_SIZE);
const int16_t aic_id = get_block_idx();
const int16_t aiv_id_per_group = AscendC::GetSubBlockIdx();
const int16_t group_num = AscendC::GetBlockNum();
const int16_t subgroup_num = get_subblockdim();
const int16_t aiv_id = aic_id * subgroup_num + aiv_id_per_group;
const int16_t aiv_num = group_num * subgroup_num;
AscendC::GlobalTensor<float> gm_input_tensor, gm_output_tensor;
gm_input_tensor.SetGlobalBuffer(reinterpret_cast<__gm__ float *>(gm_input));
gm_output_tensor.SetGlobalBuffer(reinterpret_cast<__gm__ float *>(gm_output));
AsdopsBuffer<ArchType::ASCEND_V220> buf;
const int32_t max_num = 24 * 1024 / sizeof(float);
int32_t now_UB = 0;
auto buf1_input = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += 2 * max_num * sizeof(float);
auto buf2_output_real = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_output_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf2_input = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += 2 * max_num * sizeof(float);
auto buf1_output_real = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
auto buf1_output_imag = buf.GetBuffer<BufferType::ASCEND_UB, float>((uintptr_t)now_UB);
now_UB += max_num * sizeof(float);
int32_t N2_max_num = max_num;
int32_t N1_max_num = N2_max_num / ROUND(N2, tile_N0); // 64
N1_max_num = N1_max_num + (N1_max_num == 0);
int32_t batch_max_num;
N1_max_num = MIN(N1_max_num, N1); // 64
N2_max_num = MIN(N2_max_num, ROUND(N2, tile_N0)); // 96
batch_max_num = max_num / (N1_max_num * N2_max_num); // 1
batch_max_num += (batch_max_num == 0);
int32_t N1_loop = (N1 + N1_max_num - 1) / N1_max_num; // 2
// 除0整改
if (N1_loop == 0) {
N1_loop = 1;
}
const int32_t N2_loop = (int32_t)((N2 + N2_max_num - 1) / N2_max_num); // 1
int64_t batch_loop = (batchSize + batch_max_num - 1) / batch_max_num; // batchSize
// 除0整改
if (batch_loop == 0) {
batch_loop = 1;
}
const int32_t batch_remain = batchSize % batch_max_num;
const int32_t N2_remain = N2 % N2_max_num; // 81
const int32_t N1_remain = N1 % N1_max_num; // 17
const int64_t loop = batch_loop * N1_loop * N2_loop; // batch * 2
AscendC::Duplicate<float>(buf2_output_imag, 0.0, 24 * 1024 / sizeof(float));
PIPE_BARRIER(V);
bool flag = 0;
SET_FLAG(MTE3, MTE2, EVENT_ID0);
SET_FLAG(MTE3, MTE2, EVENT_ID1);
for (int64_t i = 0; i < loop; i++) {
int64_t loop_idx = i;
if (loop_idx % static_cast<int64_t>(aiv_num) != static_cast<int64_t>(aiv_id)) {
continue;
}
int64_t N1_idx = loop_idx % N1_loop;
int64_t batch_N2_idx = loop_idx / N1_loop;
int64_t batch_idx = batch_N2_idx % batch_loop;
int64_t N2_block_idx = batch_N2_idx / batch_loop;
int32_t N2_actual = N2_max_num;
if (N2_block_idx == N2_loop - 1 && N2_remain > 0) {
N2_actual = N2_remain;
}
int32_t N1_actual = N1_max_num;
if (N1_idx == N1_loop - 1 && N1_remain > 0) {
N1_actual = N1_remain;
}
int32_t batch_actual = batch_max_num;
if (batch_idx == batch_loop - 1 && batch_remain > 0) {
batch_actual = batch_remain;
}
int32_t N2_actual_round = ROUND(N2_actual, tile_N0);
auto buf_input = flag ? buf1_input : buf2_input;
auto buf_output_real = flag ? buf1_output_real : buf2_output_real;
auto buf_output_imag = buf2_output_imag;
auto event_id = flag ? EVENT_ID0 : EVENT_ID1;
WAIT_FLAG(MTE3, MTE2, event_id);
const int64_t data_input_index =
batch_idx * batch_max_num * N1 * N2 + N1_idx * N1_max_num * N2 + N2_block_idx * N2_max_num;
copy_gm2ubuf(buf_output_real, gm_input_tensor[data_input_index], batch_actual * N1_actual, ROUND(N2_actual, 8), N2, N2_actual_round);
SET_FLAG(MTE2, V, event_id);
WAIT_FLAG(MTE2, V, event_id);
const int64_t data_output_index = batch_idx * batch_max_num * 2 * N1 * N2_padding +
N1_idx * N1_max_num * tile_N0 + N2_block_idx * 2 * N1 * N2_max_num;
auto gm_output_real_ptr = gm_output_tensor[data_output_index];
auto gm_output_imag_ptr = gm_output_tensor[data_output_index + N1 * tile_N0];
// 按照不同shape来合并访存
if (N1_actual == N1 && N2_actual == N2 && N2 <= tile_N0) {
AscendC::DataCopy(buf_input,
buf_output_real,
AscendC::DataCopyParams(
batch_actual,
N1_actual * N2_actual_round / C0_SIZE,
0,
(2 * N1_actual * N2_actual_round - N1_actual * N2_actual_round) / C0_SIZE
)
);
AscendC::DataCopy(buf_input[N1_actual * N2_actual_round],
buf_output_imag,
AscendC::DataCopyParams(
batch_actual,
N1_actual * N2_actual_round / C0_SIZE,
0,
(2 * N1_actual * N2_actual_round - N1_actual * N2_actual_round) / C0_SIZE
)
);
SET_FLAG(V, MTE3, event_id);
WAIT_FLAG(V, MTE3, event_id);
copy_ubuf2gm(gm_output_real_ptr, buf_input, batch_actual, 2 * N1_actual * tile_N0, 2 * N1_actual * tile_N0,
2 * N1 * tile_N0);
} else if (batch_max_num == 1 && N2_actual == N2 && N2 <= tile_N0) {
SET_FLAG(V, MTE3, event_id);
SET_FLAG(V, MTE3, event_id + 2);
WAIT_FLAG(V, MTE3, event_id);
copy_ubuf2gm(gm_output_real_ptr, buf_output_real, batch_actual, N1_actual * tile_N0, N1_actual * tile_N0,
2 * N1 * tile_N0);
WAIT_FLAG(V, MTE3, event_id + 2);
copy_ubuf2gm(gm_output_imag_ptr, buf_output_imag, batch_actual, N1_actual * tile_N0, N1_actual * tile_N0,
2 * N1 * tile_N0);
} else if (batch_max_num == 1 && N1_max_num == 1) {
SET_FLAG(V, MTE3, event_id);
SET_FLAG(V, MTE3, event_id + 2);
WAIT_FLAG(V, MTE3, event_id);
AscendC::DataCopyPad(gm_output_real_ptr,
buf_output_real,
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - tile_N0) * sizeof(float), 0));
WAIT_FLAG(V, MTE3, event_id + 2);
AscendC::DataCopyPad(gm_output_imag_ptr,
buf_output_imag,
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - tile_N0) * sizeof(float), 0));
} else {
for (int32_t j = 0; j < batch_actual; j++) {
for (int32_t i = 0; i < N1_actual; i++) {
AscendC::DataCopy(buf_input[j * 2 * N1_actual * N2_actual_round + i * tile_N0],
buf_output_real[j * N1_actual * N2_actual_round + i * N2_actual_round],
AscendC::DataCopyParams(
N2_actual_round / tile_N0,
tile_N0 / C0_SIZE,
0,
(N1_actual * tile_N0 - tile_N0) / C0_SIZE
)
);
AscendC::DataCopy(buf_input[j * 2 * N1_actual * N2_actual_round + N1_actual * N2_actual_round + i * tile_N0],
buf_output_imag[j * N1_actual * N2_actual_round + i * N2_actual_round],
AscendC::DataCopyParams(
N2_actual_round / tile_N0,
tile_N0 / C0_SIZE,
0,
(N1_actual * tile_N0 - tile_N0) / C0_SIZE
)
);
}
}
SET_FLAG(V, MTE3, event_id);
WAIT_FLAG(V, MTE3, event_id);
for (int32_t j = 0; j < batch_actual; j++) {
AscendC::DataCopyPad(gm_output_real_ptr[j * 2 * N1 * N2_padding],
buf_input[j * 2 * N1_actual * N2_actual_round],
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, N1_actual * tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - N1_actual * tile_N0) * sizeof(float), 0));
AscendC::DataCopyPad(gm_output_imag_ptr[j * 2 * N1 * N2_padding],
buf_input[j * 2 * N1_actual * N2_actual_round + N1_actual * N2_actual_round],
AscendC::DataCopyExtParams(N2_actual_round / tile_N0, N1_actual * tile_N0 * sizeof(float),
0, (2 * N1 * tile_N0 - N1_actual * tile_N0) * sizeof(float), 0));
}
}
SET_FLAG(MTE3, MTE2, event_id);
flag = 1 - flag;
}
WAIT_FLAG(MTE3, MTE2, EVENT_ID0);
WAIT_FLAG(MTE3, MTE2, EVENT_ID1);
}