| @@ -105,7 +105,7 @@ __simd_callee__ inline void LocalMemBar() | |||
| 105 | 105 | ||
| 106 | ## 调用示例<a name="section642mcpsimp"></a> | 106 | ## 调用示例<a name="section642mcpsimp"></a> |
| 107 | 107 | ||
| 108 | -如下示例中dstPtr和src0Ptr为同一个Unified Buffer(UB)地址,for循环的第二次迭代中读UB矢量搬运和第一次迭代中写UB矢量搬运操作了同一块UB地址空间,因此第二次循环中读UB矢量搬运需要等待第一次循环中写UB矢量搬运执行完成后才能执行,需要插入VEC_LOAD等待VEC_STORE的同步。 | 108 | +如下示例中`dstAddr`和`src0Addr`为同一个Unified Buffer(UB)地址,for循环的第二次迭代中读UB矢量搬运和第一次迭代中写UB矢量搬运操作了同一块UB地址空间,因此第二次循环中读UB矢量搬运需要等待第一次循环中写UB矢量搬运执行完成后才能执行,需要插入VEC_LOAD等待VEC_STORE的同步。 |
| 109 | 109 | ||
| 110 | ```cpp | 110 | ```cpp |
| 111 | template<typename T> | 111 | template<typename T> |
| @@ -177,7 +177,7 @@ __global__ __mix__(1, 2) void MatmulScaleKernel( | |||
| 177 | asc_copy_ub2gm_align(output + aiv_index * ELEMENTS_PER_AIV, output_ub, FP32_BYTES_PER_AIV); | 177 | asc_copy_ub2gm_align(output + aiv_index * ELEMENTS_PER_AIV, output_ub, FP32_BYTES_PER_AIV); |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | - asc_sync_pipe(PIPE_ALL); | 180 | + asc_sync(); |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | bool CheckResult(const std::vector<float>& matmul_result, const std::vector<float>& output) | 183 | bool CheckResult(const std::vector<float>& matmul_result, const std::vector<float>& output) |
| @@ -355,7 +355,7 @@ __global__ __cube__ void asc_mmad_kernel(__gm__ int8_t* a, __gm__ int8_t* b, __g | |||
| 355 | asc_set_l0c_copy_nz_para(1, 0, 0); | 355 | asc_set_l0c_copy_nz_para(1, 0, 0); |
| 356 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, | 356 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, |
| 357 | asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, asc_relu_pre_mode::NONE, false, true, false, false); | 357 | asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, asc_relu_pre_mode::NONE, false, true, false, false); |
| 358 | - asc_sync_pipe(PIPE_ALL); | 358 | + asc_sync(); |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | template <typename T> | 361 | template <typename T> |
| @@ -279,7 +279,7 @@ __global__ __cube__ void asc_mmad_mx_kernel(__gm__ uint8_t* a, __gm__ uint8_t* s | |||
| 279 | asc_set_l0c_copy_nz_para(1, 0, 0); | 279 | asc_set_l0c_copy_nz_para(1, 0, 0); |
| 280 | asc_copy_l0c2gm(output, c_l0, N, M, N, M_ALIGN, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, | 280 | asc_copy_l0c2gm(output, c_l0, N, M, N, M_ALIGN, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, |
| 281 | asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, asc_relu_pre_mode::NONE, false, true, false, false); | 281 | asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, asc_relu_pre_mode::NONE, false, true, false, false); |
| 282 | - asc_sync_pipe(PIPE_ALL); | 282 | + asc_sync(); |
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | void print_row(const char* label, const std::vector<float>& data) | 285 | void print_row(const char* label, const std::vector<float>& data) |
| @@ -120,7 +120,7 @@ __global__ __cube__ void asc_disable_hf32_kernel( | |||
| 120 | asc_copy_l0c2gm(fp32_output, fp32_l0, DIM, DIM, DIM, DIM, | 120 | asc_copy_l0c2gm(fp32_output, fp32_l0, DIM, DIM, DIM, DIM, |
| 121 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, | 121 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, |
| 122 | asc_relu_pre_mode::NONE, false, true, false, false); | 122 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 123 | - asc_sync_pipe(PIPE_ALL); | 123 | + asc_sync(); |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | void print_row(const char* label, const std::vector<float>& data) | 126 | void print_row(const char* label, const std::vector<float>& data) |
| @@ -127,7 +127,7 @@ __global__ __cube__ void asc_disable_hif8_kernel( | |||
| 127 | asc_copy_l0c2gm(fp8_output, fp8_l0, N, M, N, M, | 127 | asc_copy_l0c2gm(fp8_output, fp8_l0, N, M, N, M, |
| 128 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, | 128 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, |
| 129 | asc_relu_pre_mode::NONE, false, true, false, false); | 129 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 130 | - asc_sync_pipe(PIPE_ALL); | 130 | + asc_sync(); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | void print_row(const char* label, const std::vector<float>& data) | 133 | void print_row(const char* label, const std::vector<float>& data) |
| @@ -182,7 +182,7 @@ __global__ __cube__ void asc_enable_hf32_kernel( | |||
| 182 | asc_copy_l0c2gm(hf32_output, hf32_l0, DIM, DIM, DIM, DIM, | 182 | asc_copy_l0c2gm(hf32_output, hf32_l0, DIM, DIM, DIM, DIM, |
| 183 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, | 183 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, |
| 184 | asc_relu_pre_mode::NONE, false, true, false, false); | 184 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 185 | - asc_sync_pipe(PIPE_ALL); | 185 | + asc_sync(); |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | void print_row(const char* label, const std::vector<float>& data) | 188 | void print_row(const char* label, const std::vector<float>& data) |
| @@ -108,7 +108,7 @@ __global__ __cube__ void asc_enable_hif8_kernel( | |||
| 108 | asc_copy_l0c2gm(hif8_output, hif8_l0, N, M, N, M, | 108 | asc_copy_l0c2gm(hif8_output, hif8_l0, N, M, N, M, |
| 109 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, | 109 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, |
| 110 | asc_relu_pre_mode::NONE, false, true, false, false); | 110 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 111 | - asc_sync_pipe(PIPE_ALL); | 111 | + asc_sync(); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | void print_row(const char* label, const std::vector<float>& data) | 114 | void print_row(const char* label, const std::vector<float>& data) |
| @@ -112,7 +112,7 @@ __global__ __cube__ void asc_set_hf32_round_mode_kernel( | |||
| 112 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, | 112 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, |
| 113 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, | 113 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, |
| 114 | asc_relu_pre_mode::NONE, false, true, false, false); | 114 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 115 | - asc_sync_pipe(PIPE_ALL); | 115 | + asc_sync(); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | void print_row(const char* label, const std::vector<float>& data) | 118 | void print_row(const char* label, const std::vector<float>& data) |
| @@ -114,7 +114,7 @@ __global__ __cube__ void asc_set_mmad_direction_m_kernel( | |||
| 114 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, | 114 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, |
| 115 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, | 115 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, |
| 116 | asc_relu_pre_mode::NONE, false, true, false, false); | 116 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 117 | - asc_sync_pipe(PIPE_ALL); | 117 | + asc_sync(); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | void print_row(const char* label, const std::vector<int32_t>& data) | 120 | void print_row(const char* label, const std::vector<int32_t>& data) |
| @@ -113,7 +113,7 @@ __global__ __cube__ void asc_set_mmad_direction_n_kernel( | |||
| 113 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, | 113 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, |
| 114 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, | 114 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::NoQuant, |
| 115 | asc_relu_pre_mode::NONE, false, true, false, false); | 115 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 116 | - asc_sync_pipe(PIPE_ALL); | 116 | + asc_sync(); |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | void print_row(const char* label, const std::vector<int32_t>& data) | 119 | void print_row(const char* label, const std::vector<int32_t>& data) |
| @@ -177,7 +177,7 @@ __global__ __cube__ void AscCopyGm2l1TwoDimNzKernel( | |||
| 177 | // 关闭Nz2ND和Nz2DN,保持L0C Buffer中的Nz排布直接搬出至GM。 | 177 | // 关闭Nz2ND和Nz2DN,保持L0C Buffer中的Nz排布直接搬出至GM。 |
| 178 | asc_copy_l0c2gm(output, c_l0, N, M, M * CUBE, M, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, | 178 | asc_copy_l0c2gm(output, c_l0, N, M, M * CUBE, M, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, |
| 179 | asc_unit_flag_mode::DISABLE, QuantMode_t::NoQuant, asc_relu_pre_mode::NONE, false, false, false, false); | 179 | asc_unit_flag_mode::DISABLE, QuantMode_t::NoQuant, asc_relu_pre_mode::NONE, false, false, false, false); |
| 180 | - asc_sync_pipe(PIPE_ALL); | 180 | + asc_sync(); |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | uint16_t ToHalfBits(int32_t value) | 183 | uint16_t ToHalfBits(int32_t value) |
| @@ -244,7 +244,7 @@ __global__ __mix__(1, 2) void asc_copy_gm2l1_align_modes_kernel( // __mix__: | |||
| 244 | asc_sync_pipe(PIPE_MTE1); | 244 | asc_sync_pipe(PIPE_MTE1); |
| 245 | asc_sync_intra_arrive(PIPE_MTE1, AIC_TO_AIV_SYNC_ID); | 245 | asc_sync_intra_arrive(PIPE_MTE1, AIC_TO_AIV_SYNC_ID); |
| 246 | } | 246 | } |
| 247 | - asc_sync_pipe(PIPE_ALL); | 247 | + asc_sync(); |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | std::vector<uint8_t> MakeInput() | 250 | std::vector<uint8_t> MakeInput() |
| @@ -163,7 +163,7 @@ __global__ __cube__ void AscCopyGm2l1HighdimBiasKernel( | |||
| 163 | asc_set_l0c_copy_nz_para(1, 0, 0); | 163 | asc_set_l0c_copy_nz_para(1, 0, 0); |
| 164 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, | 164 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, |
| 165 | asc_unit_flag_mode::DISABLE, QuantMode_t::NoQuant, asc_relu_pre_mode::NONE, false, true, false, false); | 165 | asc_unit_flag_mode::DISABLE, QuantMode_t::NoQuant, asc_relu_pre_mode::NONE, false, true, false, false); |
| 166 | - asc_sync_pipe(PIPE_ALL); | 166 | + asc_sync(); |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | uint16_t ToHalfBits(int32_t value) | 169 | uint16_t ToHalfBits(int32_t value) |
| @@ -158,7 +158,7 @@ __global__ __cube__ void CopyL12btKernel(__gm__ half* input) | |||
| 158 | asc_sync_notify(PIPE_MTE2, PIPE_MTE1, EVENT_ID0); | 158 | asc_sync_notify(PIPE_MTE2, PIPE_MTE1, EVENT_ID0); |
| 159 | asc_sync_wait(PIPE_MTE2, PIPE_MTE1, EVENT_ID0); | 159 | asc_sync_wait(PIPE_MTE2, PIPE_MTE1, EVENT_ID0); |
| 160 | asc_copy_l12bt(0, l1, BYTES); | 160 | asc_copy_l12bt(0, l1, BYTES); |
| 161 | - asc_sync_pipe(PIPE_ALL); | 161 | + asc_sync(); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | int main() | 164 | int main() |
| @@ -243,7 +243,7 @@ __global__ __cube__ void asc_copy_l12l0b_3d_bside_kernel( | |||
| 243 | asc_copy_l0c2gm( | 243 | asc_copy_l0c2gm( |
| 244 | output, output_l0, M, COUT, M, COUT, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, | 244 | output, output_l0, M, COUT, M, COUT, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, |
| 245 | asc_unit_flag_mode::DISABLE, QuantMode_t::F322F16, asc_relu_pre_mode::NONE, false, true, false, false); | 245 | asc_unit_flag_mode::DISABLE, QuantMode_t::F322F16, asc_relu_pre_mode::NONE, false, true, false, false); |
| 246 | - asc_sync_pipe(PIPE_ALL); | 246 | + asc_sync(); |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | } // namespace | 249 | } // namespace |
| @@ -238,7 +238,7 @@ __global__ __mix__(1, 2) void CopyL0c2l1Kernel( | |||
| 238 | if (asc_get_sub_block_id() == 0) | 238 | if (asc_get_sub_block_id() == 0) |
| 239 | asc_copy_ub2gm_align(output, output_ub, ELEMENTS * sizeof(int32_t)); | 239 | asc_copy_ub2gm_align(output, output_ub, ELEMENTS * sizeof(int32_t)); |
| 240 | } | 240 | } |
| 241 | - asc_sync_pipe(PIPE_ALL); | 241 | + asc_sync(); |
| 242 | } | 242 | } |
| 243 | } // namespace | 243 | } // namespace |
| 244 | 244 | ||
| @@ -254,7 +254,7 @@ __global__ __mix__(1, 2) void AscCopyL0c2ubKernel(__gm__ int8_t* a, __gm__ int8_ | |||
| 254 | asc_sync_block_wait(PIPE_MTE3, 0x8); | 254 | asc_sync_block_wait(PIPE_MTE3, 0x8); |
| 255 | asc_copy_ub2gm(output, output_ub, M, N * sizeof(int32_t), | 255 | asc_copy_ub2gm(output, output_ub, M, N * sizeof(int32_t), |
| 256 | N * sizeof(int32_t), N * sizeof(int32_t)); | 256 | N * sizeof(int32_t), N * sizeof(int32_t)); |
| 257 | - asc_sync_pipe(PIPE_ALL); | 257 | + asc_sync(); |
| 258 | } | 258 | } |
| 259 | } | 259 | } |
| 260 | 260 | ||
| @@ -117,7 +117,7 @@ __global__ __mix__(1, 2) void CopyL12ubKernel(__gm__ uint8_t* input, __gm__ uint | |||
| 117 | asc_copy_ub2gm_align(output, ub, BYTES); | 117 | asc_copy_ub2gm_align(output, ub, BYTES); |
| 118 | } | 118 | } |
| 119 | } | 119 | } |
| 120 | - asc_sync_pipe(PIPE_ALL); | 120 | + asc_sync(); |
| 121 | } | 121 | } |
| 122 | } // namespace | 122 | } // namespace |
| 123 | 123 | ||
| @@ -131,7 +131,7 @@ __global__ __mix__(1, 2) void LoopKernel( // __mix__:AIC搬运到L1,AIV将 | |||
| 131 | asc_sync_pipe(PIPE_MTE1); | 131 | asc_sync_pipe(PIPE_MTE1); |
| 132 | asc_sync_intra_arrive(PIPE_MTE1, AIC_TO_AIV_SYNC_ID); | 132 | asc_sync_intra_arrive(PIPE_MTE1, AIC_TO_AIV_SYNC_ID); |
| 133 | } | 133 | } |
| 134 | - asc_sync_pipe(PIPE_ALL); | 134 | + asc_sync(); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | bool IsGolden(const std::vector<uint8_t>& output) | 137 | bool IsGolden(const std::vector<uint8_t>& output) |
| @@ -149,7 +149,7 @@ __global__ __cube__ void asc_set_gm2l1_nz_para_kernel( | |||
| 149 | asc_set_l0c_copy_nz_para(1, 0, 0); | 149 | asc_set_l0c_copy_nz_para(1, 0, 0); |
| 150 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, | 150 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, |
| 151 | asc_unit_flag_mode::DISABLE, QuantMode_t::NoQuant, asc_relu_pre_mode::NONE, false, true, false, false); | 151 | asc_unit_flag_mode::DISABLE, QuantMode_t::NoQuant, asc_relu_pre_mode::NONE, false, true, false, false); |
| 152 | - asc_sync_pipe(PIPE_ALL); | 152 | + asc_sync(); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | void print_row(const char* label, const std::vector<float>& data) | 155 | void print_row(const char* label, const std::vector<float>& data) |
| @@ -139,7 +139,7 @@ __global__ __mix__(1, 2) void asc_set_gm2l1_padding_kernel( // __mix__:AIC配 | |||
| 139 | asc_sync_pipe(PIPE_MTE1); | 139 | asc_sync_pipe(PIPE_MTE1); |
| 140 | asc_sync_intra_arrive(PIPE_MTE1, AIC_TO_AIV_SYNC_ID); | 140 | asc_sync_intra_arrive(PIPE_MTE1, AIC_TO_AIV_SYNC_ID); |
| 141 | } | 141 | } |
| 142 | - asc_sync_pipe(PIPE_ALL); | 142 | + asc_sync(); |
| 143 | } | 143 | } |
| 144 | } // namespace | 144 | } // namespace |
| 145 | 145 | ||
| @@ -190,7 +190,7 @@ __global__ __cube__ void Conv2dForwardCapi( | |||
| 190 | output + batch_idx * OUTPUT_BATCH_SIZE, output_l0, N, M, N, M_ALIGN, | 190 | output + batch_idx * OUTPUT_BATCH_SIZE, output_l0, N, M, N, M_ALIGN, |
| 191 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, QuantMode_t::F322F16, | 191 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, QuantMode_t::F322F16, |
| 192 | asc_relu_pre_mode::NONE, false, true, false, false); | 192 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 193 | - asc_sync_pipe(PIPE_ALL); | 193 | + asc_sync(); |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | size_t FmapIndex(uint32_t n, uint32_t h, uint32_t w, uint32_t c) | 196 | size_t FmapIndex(uint32_t n, uint32_t h, uint32_t w, uint32_t c) |
| @@ -153,7 +153,7 @@ __global__ __cube__ void asc_copy_l12l0b_3d_bside_kernel( | |||
| 153 | asc_copy_l0c2gm( | 153 | asc_copy_l0c2gm( |
| 154 | output, output_l0, M, COUT, M, COUT, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, | 154 | output, output_l0, M, COUT, M, COUT, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, |
| 155 | asc_unit_flag_mode::DISABLE, QuantMode_t::F322F16, asc_relu_pre_mode::NONE, false, true, false, false); | 155 | asc_unit_flag_mode::DISABLE, QuantMode_t::F322F16, asc_relu_pre_mode::NONE, false, true, false, false); |
| 156 | - asc_sync_pipe(PIPE_ALL); | 156 | + asc_sync(); |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | } // namespace | 159 | } // namespace |
| @@ -179,7 +179,7 @@ __global__ __cube__ void conv2d_forward_c_api( | |||
| 179 | asc_copy_l0c2gm(output + batch_idx * OUTPUT_BATCH_SIZE, output_l0, N, M, N, M_ALIGN, | 179 | asc_copy_l0c2gm(output + batch_idx * OUTPUT_BATCH_SIZE, output_l0, N, M, N, M_ALIGN, |
| 180 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, | 180 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, |
| 181 | asc_relu_pre_mode::NONE, false, true, false, false); | 181 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 182 | - asc_sync_pipe(PIPE_ALL); | 182 | + asc_sync(); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | size_t fmap_index(uint32_t n, uint32_t h, uint32_t w, uint32_t c) | 185 | size_t fmap_index(uint32_t n, uint32_t h, uint32_t w, uint32_t c) |
| @@ -153,7 +153,7 @@ __global__ __cube__ void asc_set_l13d_fmatrix_b_kernel( | |||
| 153 | asc_copy_l0c2gm(output, output_l0, M, COUT, M, COUT, | 153 | asc_copy_l0c2gm(output, output_l0, M, COUT, M, COUT, |
| 154 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, | 154 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, |
| 155 | asc_relu_pre_mode::NONE, false, true, false, false); | 155 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 156 | - asc_sync_pipe(PIPE_ALL); | 156 | + asc_sync(); |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | } // namespace | 159 | } // namespace |
| @@ -178,7 +178,7 @@ __global__ __cube__ void conv2d_forward_c_api( | |||
| 178 | asc_copy_l0c2gm(output + batch_idx * OUTPUT_BATCH_SIZE, output_l0, N, M, N, M_ALIGN, | 178 | asc_copy_l0c2gm(output + batch_idx * OUTPUT_BATCH_SIZE, output_l0, N, M, N, M_ALIGN, |
| 179 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, | 179 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, |
| 180 | asc_relu_pre_mode::NONE, false, true, false, false); | 180 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 181 | - asc_sync_pipe(PIPE_ALL); | 181 | + asc_sync(); |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | size_t fmap_index(uint32_t n, uint32_t h, uint32_t w, uint32_t c) | 184 | size_t fmap_index(uint32_t n, uint32_t h, uint32_t w, uint32_t c) |
| @@ -148,7 +148,7 @@ __global__ __cube__ void asc_set_l13d_rpt_b_kernel( | |||
| 148 | asc_copy_l0c2gm(output, output_l0, M, COUT, M, COUT, | 148 | asc_copy_l0c2gm(output, output_l0, M, COUT, M, COUT, |
| 149 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, | 149 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, |
| 150 | asc_relu_pre_mode::NONE, false, true, false, false); | 150 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 151 | - asc_sync_pipe(PIPE_ALL); | 151 | + asc_sync(); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | } // namespace | 154 | } // namespace |
| @@ -153,7 +153,7 @@ __global__ __cube__ void asc_set_l13d_rpt_b_kernel( | |||
| 153 | asc_copy_l0c2gm(output, output_l0, M, COUT, M, COUT, | 153 | asc_copy_l0c2gm(output, output_l0, M, COUT, M, COUT, |
| 154 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, | 154 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, |
| 155 | asc_relu_pre_mode::NONE, false, true, false, false); | 155 | asc_relu_pre_mode::NONE, false, true, false, false); |
| 156 | - asc_sync_pipe(PIPE_ALL); | 156 | + asc_sync(); |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | } // namespace | 159 | } // namespace |
| @@ -122,7 +122,7 @@ __global__ __cube__ void asc_set_l0c_copy_channel_para_kernel( | |||
| 122 | asc_set_l0c_copy_nz_para(1, 0, 0); | 122 | asc_set_l0c_copy_nz_para(1, 0, 0); |
| 123 | asc_copy_l0c2gm(output, c_l0, N, M, M, M, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, | 123 | asc_copy_l0c2gm(output, c_l0, N, M, M, M, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, |
| 124 | asc_unit_flag_mode::DISABLE, QuantMode_t::NoQuant, asc_relu_pre_mode::NONE, false, false, true, false); | 124 | asc_unit_flag_mode::DISABLE, QuantMode_t::NoQuant, asc_relu_pre_mode::NONE, false, false, true, false); |
| 125 | - asc_sync_pipe(PIPE_ALL); | 125 | + asc_sync(); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | void print_row(const char* label, const std::vector<float>& data, uint32_t offset) | 128 | void print_row(const char* label, const std::vector<float>& data, uint32_t offset) |
| @@ -151,7 +151,7 @@ __global__ __cube__ void asc_set_l0c_copy_config_kernel( | |||
| 151 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, | 151 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, |
| 152 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, | 152 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, |
| 153 | asc_quant_mode::VQF322B8_PRE, asc_relu_pre_mode::NONE, false, true, false, false); | 153 | asc_quant_mode::VQF322B8_PRE, asc_relu_pre_mode::NONE, false, true, false, false); |
| 154 | - asc_sync_pipe(PIPE_ALL); | 154 | + asc_sync(); |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | void print_row(const char* label, const std::vector<int8_t>& data) | 157 | void print_row(const char* label, const std::vector<int8_t>& data) |
| @@ -119,7 +119,7 @@ __global__ __cube__ void asc_set_l0c_copy_lrelu_alpha_kernel( | |||
| 119 | asc_copy_l0c2gm(reinterpret_cast<__gm__ half*>(output), c_l0, DIM, DIM, DIM, DIM, | 119 | asc_copy_l0c2gm(reinterpret_cast<__gm__ half*>(output), c_l0, DIM, DIM, DIM, DIM, |
| 120 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, | 120 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, |
| 121 | asc_relu_pre_mode::SCALAR, false, true, false, false); | 121 | asc_relu_pre_mode::SCALAR, false, true, false, false); |
| 122 | - asc_sync_pipe(PIPE_ALL); | 122 | + asc_sync(); |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | void print_row(const char* label, const std::vector<uint16_t>& data) | 125 | void print_row(const char* label, const std::vector<uint16_t>& data) |
| @@ -114,7 +114,7 @@ __global__ __cube__ void asc_set_l0c_copy_nz_para_kernel( | |||
| 114 | asc_set_l0c_copy_nz_para(1, 0, 0); | 114 | asc_set_l0c_copy_nz_para(1, 0, 0); |
| 115 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, | 115 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, |
| 116 | asc_unit_flag_mode::DISABLE, QuantMode_t::NoQuant, asc_relu_pre_mode::NONE, false, true, false, false); | 116 | asc_unit_flag_mode::DISABLE, QuantMode_t::NoQuant, asc_relu_pre_mode::NONE, false, true, false, false); |
| 117 | - asc_sync_pipe(PIPE_ALL); | 117 | + asc_sync(); |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | void print_row(const char* label, const std::vector<float>& data) | 120 | void print_row(const char* label, const std::vector<float>& data) |
| @@ -202,7 +202,7 @@ __global__ __cube__ void asc_set_l0c_copy_prequant_kernel( | |||
| 202 | asc_set_l0c_copy_nz_para(1, 0, 0); | 202 | asc_set_l0c_copy_nz_para(1, 0, 0); |
| 203 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, | 203 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, |
| 204 | asc_unit_flag_mode::DISABLE, QuantMode_t::QF322B8_PRE, asc_relu_pre_mode::NONE, false, true, false, false); | 204 | asc_unit_flag_mode::DISABLE, QuantMode_t::QF322B8_PRE, asc_relu_pre_mode::NONE, false, true, false, false); |
| 205 | - asc_sync_pipe(PIPE_ALL); | 205 | + asc_sync(); |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | void print_row(const char* label, const std::vector<int8_t>& data) | 208 | void print_row(const char* label, const std::vector<int8_t>& data) |
| @@ -122,7 +122,7 @@ __global__ __cube__ void asc_set_l0c_copy_relu_alpha_kernel( | |||
| 122 | asc_copy_l0c2gm(reinterpret_cast<__gm__ half*>(output), c_l0, DIM, DIM, DIM, DIM, | 122 | asc_copy_l0c2gm(reinterpret_cast<__gm__ half*>(output), c_l0, DIM, DIM, DIM, DIM, |
| 123 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, | 123 | asc_store_l2_cache_mode::NORMAL_FIRST_VICTIM, asc_unit_flag_mode::DISABLE, asc_quant_mode::F322F16, |
| 124 | asc_relu_pre_mode::SCALAR, false, true, false, false); | 124 | asc_relu_pre_mode::SCALAR, false, true, false, false); |
| 125 | - asc_sync_pipe(PIPE_ALL); | 125 | + asc_sync(); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | void print_row(const char* label, const std::vector<uint16_t>& data) | 128 | void print_row(const char* label, const std::vector<uint16_t>& data) |
| @@ -197,7 +197,7 @@ __global__ __cube__ void AscCopyGm2l1TwoDimNzKernel( | |||
| 197 | asc_copy_l0c2gm(output, c_l0, N, M, M * CUBE, M, 0, 0, 0, | 197 | asc_copy_l0c2gm(output, c_l0, N, M, M * CUBE, M, 0, 0, 0, |
| 198 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, false, | 198 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, false, |
| 199 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); | 199 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); |
| 200 | - asc_sync_pipe(PIPE_ALL); | 200 | + asc_sync(); |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | uint16_t ToHalfBits(int32_t value) | 203 | uint16_t ToHalfBits(int32_t value) |
| @@ -264,7 +264,7 @@ __global__ __mix__(1, 2) void asc_copy_gm2l1_align_modes_kernel( // __mix__: | |||
| 264 | asc_sync_pipe(PIPE_MTE1); | 264 | asc_sync_pipe(PIPE_MTE1); |
| 265 | asc_sync_intra_arrive(PIPE_MTE1, AIC_TO_AIV_SYNC_ID); | 265 | asc_sync_intra_arrive(PIPE_MTE1, AIC_TO_AIV_SYNC_ID); |
| 266 | } | 266 | } |
| 267 | - asc_sync_pipe(PIPE_ALL); | 267 | + asc_sync(); |
| 268 | } | 268 | } |
| 269 | 269 | ||
| 270 | std::vector<uint8_t> MakeInput() | 270 | std::vector<uint8_t> MakeInput() |
| @@ -237,7 +237,7 @@ __global__ __mix__(1, 2) void asc_copy_gm2l1_align_modes_kernel( // __mix__: | |||
| 237 | asc_sync_pipe(PIPE_MTE1); | 237 | asc_sync_pipe(PIPE_MTE1); |
| 238 | asc_sync_intra_arrive(PIPE_MTE1, AIC_TO_AIV_SYNC_ID); | 238 | asc_sync_intra_arrive(PIPE_MTE1, AIC_TO_AIV_SYNC_ID); |
| 239 | } | 239 | } |
| 240 | - asc_sync_pipe(PIPE_ALL); | 240 | + asc_sync(); |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | std::vector<uint8_t> MakeInput() | 243 | std::vector<uint8_t> MakeInput() |
| @@ -167,7 +167,7 @@ __global__ __cube__ void AscCopyGm2l1HighdimBiasKernel( | |||
| 167 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, 0, 0, 0, | 167 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, 0, 0, 0, |
| 168 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, true, | 168 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, true, |
| 169 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); | 169 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); |
| 170 | - asc_sync_pipe(PIPE_ALL); | 170 | + asc_sync(); |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | uint16_t ToHalfBits(int32_t value) | 173 | uint16_t ToHalfBits(int32_t value) |
| @@ -173,7 +173,7 @@ __global__ __cube__ void AscCopyGm2l1TwoDimNzKernel( | |||
| 173 | asc_copy_l0c2gm(output, c_l0, N, M, M * CUBE, M, 0, 0, 0, | 173 | asc_copy_l0c2gm(output, c_l0, N, M, M * CUBE, M, 0, 0, 0, |
| 174 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, false, | 174 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, false, |
| 175 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); | 175 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); |
| 176 | - asc_sync_pipe(PIPE_ALL); | 176 | + asc_sync(); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | uint16_t ToHalfBits(int32_t value) | 179 | uint16_t ToHalfBits(int32_t value) |
| @@ -164,7 +164,7 @@ __global__ __cube__ void AscCopyGm2l1HighdimBiasKernel( | |||
| 164 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, 0, 0, 0, | 164 | asc_copy_l0c2gm(output, c_l0, N, M, N, M, 0, 0, 0, |
| 165 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, true, | 165 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, true, |
| 166 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); | 166 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); |
| 167 | - asc_sync_pipe(PIPE_ALL); | 167 | + asc_sync(); |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | uint16_t ToHalfBits(int32_t value) | 170 | uint16_t ToHalfBits(int32_t value) |
| @@ -220,7 +220,7 @@ __global__ __cube__ void asc_copy_l12l0b_3d_bside_kernel( | |||
| 220 | asc_copy_l0c2gm( | 220 | asc_copy_l0c2gm( |
| 221 | output, output_l0, M, COUT, M, COUT, 0, 0, 0, static_cast<uint64_t>(QuantMode_t::F322F16), 0, false, | 221 | output, output_l0, M, COUT, M, COUT, 0, 0, 0, static_cast<uint64_t>(QuantMode_t::F322F16), 0, false, |
| 222 | true, 0, 0, false, 0, false, false, false, false); | 222 | true, 0, 0, false, 0, false, false, false, false); |
| 223 | - asc_sync_pipe(PIPE_ALL); | 223 | + asc_sync(); |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | } // namespace | 226 | } // namespace |
| @@ -111,7 +111,7 @@ __global__ __cube__ void asc_enable_hf32_trans_kernel( | |||
| 111 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, 0, 0, 0, | 111 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, 0, 0, 0, |
| 112 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, true, | 112 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, true, |
| 113 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); | 113 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); |
| 114 | - asc_sync_pipe(PIPE_ALL); | 114 | + asc_sync(); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | void print_row(const char* label, const std::vector<float>& data) | 117 | void print_row(const char* label, const std::vector<float>& data) |
| @@ -115,7 +115,7 @@ __global__ __cube__ void asc_set_fp32_mode_kernel( | |||
| 115 | asc_copy_l0c2gm(fp32_output, fp32_l0, DIM, DIM, DIM, DIM, 0, 0, 0, | 115 | asc_copy_l0c2gm(fp32_output, fp32_l0, DIM, DIM, DIM, DIM, 0, 0, 0, |
| 116 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, true, | 116 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, true, |
| 117 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); | 117 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); |
| 118 | - asc_sync_pipe(PIPE_ALL); | 118 | + asc_sync(); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | void print_row(const char* label, const std::vector<float>& data) | 121 | void print_row(const char* label, const std::vector<float>& data) |
| @@ -130,7 +130,7 @@ __global__ __cube__ void asc_set_l0c2gm_channel_para_kernel( | |||
| 130 | asc_copy_l0c2gm(output, c_l0, N, M, M, M, 0, 0, 0, | 130 | asc_copy_l0c2gm(output, c_l0, N, M, M, M, 0, 0, 0, |
| 131 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, false, | 131 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, false, |
| 132 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, true); | 132 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, true); |
| 133 | - asc_sync_pipe(PIPE_ALL); | 133 | + asc_sync(); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | void print_row(const char* label, const std::vector<float>& data, uint32_t offset) | 136 | void print_row(const char* label, const std::vector<float>& data, uint32_t offset) |
| @@ -115,7 +115,7 @@ __global__ __cube__ void asc_set_l0c2gm_nz2nd_kernel( | |||
| 115 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, 0, 0, 0, | 115 | asc_copy_l0c2gm(output, c_l0, DIM, DIM, DIM, DIM, 0, 0, 0, |
| 116 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, true, | 116 | static_cast<uint64_t>(QuantMode_t::NoQuant), 0, false, true, |
| 117 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); | 117 | static_cast<uint64_t>(QuantMode_post::NoConv), 0, false, 0, false, false, false, false); |
| 118 | - asc_sync_pipe(PIPE_ALL); | 118 | + asc_sync(); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | void print_row(const char* label, const std::vector<float>& data) | 121 | void print_row(const char* label, const std::vector<float>& data) |
| @@ -101,25 +101,32 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 101 | #include <iostream> | 101 | #include <iostream> |
| 102 | #include <vector> | 102 | #include <vector> |
| 103 | #include "c_api/asc_simd.h" | 103 | #include "c_api/asc_simd.h" |
| 104 | +#include "utils/std/cmath.h" | ||
| 104 | #include "acl/acl.h" | 105 | #include "acl/acl.h" |
| 105 | 106 | ||
| 106 | namespace { | 107 | namespace { |
| 107 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 108 | +constexpr uint8_t MUTEX_ID = 0; |
| 108 | -{ | ||
| 109 | - return (numerator + denominator - 1) / denominator; | ||
| 110 | -} | ||
| 111 | 109 | ||
| 112 | -constexpr uint32_t INPUT_ELEMENTS = 512; | 110 | +constexpr uint32_t INPUT_ELEMENTS = 517; |
| 113 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 111 | +constexpr uint32_t OUTPUT_ELEMENTS = 517; |
| 114 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 112 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); |
| 115 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 113 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 114 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 115 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 116 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 117 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 116 | 118 | ||
| 119 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 120 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 121 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 117 | __simd_vf__ inline void asc_load_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, | 122 | __simd_vf__ inline void asc_load_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, |
| 118 | - uint16_t one_repeat_size, uint16_t repeat_time) | 123 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 119 | { | 124 | { |
| 120 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 125 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 126 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 121 | vector_uint8_t dst_reg; | 127 | vector_uint8_t dst_reg; |
| 122 | for (uint16_t i = 0; i < repeat_time; ++i) { | 128 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 129 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 123 | asc_load(dst_reg, input + i * one_repeat_size); | 130 | asc_load(dst_reg, input + i * one_repeat_size); |
| 124 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 131 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 125 | } | 132 | } |
| @@ -128,17 +135,21 @@ __simd_vf__ inline void asc_load_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* | |||
| 128 | __global__ __vector__ void asc_load_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 135 | __global__ __vector__ void asc_load_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 129 | { | 136 | { |
| 130 | asc_init(); | 137 | asc_init(); |
| 131 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 138 | + __ubuf__ uint8_t input_local[OUTPUT_STORAGE_ELEMENTS]; |
| 132 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 139 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 140 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 133 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 141 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 134 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 142 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 135 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 143 | + |
| 136 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 144 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 137 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 145 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 146 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 138 | asc_vf_call<asc_load_vf>(output_local, input_local, one_repeat_size, repeat_time); | 147 | asc_vf_call<asc_load_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 139 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 148 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 140 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 149 | + |
| 150 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 141 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 151 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 152 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 142 | asc_sync(); | 153 | asc_sync(); |
| 143 | } | 154 | } |
| 144 | } // namespace | 155 | } // namespace |
| @@ -254,12 +254,10 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 254 | #include <iostream> | 254 | #include <iostream> |
| 255 | #include <vector> | 255 | #include <vector> |
| 256 | #include "c_api/asc_simd.h" | 256 | #include "c_api/asc_simd.h" |
| 257 | +#include "utils/std/cmath.h" | ||
| 257 | #include "acl/acl.h" | 258 | #include "acl/acl.h" |
| 258 | namespace { | 259 | namespace { |
| 259 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 260 | +constexpr uint8_t MUTEX_ID = 0; |
| 260 | -{ | ||
| 261 | - return (numerator + denominator - 1) / denominator; | ||
| 262 | -} | ||
| 263 | 261 | ||
| 264 | template <typename T> | 262 | template <typename T> |
| 265 | void print_data(const char* label, const std::vector<T>& values) | 263 | void print_data(const char* label, const std::vector<T>& values) |
| @@ -271,13 +269,21 @@ void print_data(const char* label, const std::vector<T>& values) | |||
| 271 | std::cout << std::endl; | 269 | std::cout << std::endl; |
| 272 | } | 270 | } |
| 273 | 271 | ||
| 274 | -constexpr uint32_t BUFFER_ELEMENTS = 512; | 272 | +constexpr uint32_t BUFFER_ELEMENTS = 260; |
| 273 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 274 | +constexpr uint32_t BUFFER_STORAGE_ELEMENTS = | ||
| 275 | + AscendC::Std::ceil_div(BUFFER_ELEMENTS, ELEMENTS_PER_REGISTER) * ELEMENTS_PER_REGISTER; | ||
| 275 | constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t); | 276 | constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t); |
| 277 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 278 | +constexpr uint32_t TOTAL_LENGTH = BUFFER_ELEMENTS; | ||
| 279 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 276 | __simd_vf__ inline void asc_loadalign_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, | 280 | __simd_vf__ inline void asc_loadalign_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, |
| 277 | - uint16_t one_repeat_size, uint16_t repeat_time) | 281 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 278 | { | 282 | { |
| 279 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 283 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 284 | + uint32_t remaining_length = BUFFER_ELEMENTS; | ||
| 280 | for (uint16_t i = 0; i < repeat_time; ++i) { | 285 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 286 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 281 | vector_uint8_t dst_reg; | 287 | vector_uint8_t dst_reg; |
| 282 | asc_loadalign(dst_reg, input + i * one_repeat_size); | 288 | asc_loadalign(dst_reg, input + i * one_repeat_size); |
| 283 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 289 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| @@ -287,20 +293,24 @@ __simd_vf__ inline void asc_loadalign_vf(__ubuf__ uint8_t* output, __ubuf__ uint | |||
| 287 | __global__ __vector__ void asc_loadalign_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 293 | __global__ __vector__ void asc_loadalign_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 288 | { | 294 | { |
| 289 | asc_init(); | 295 | asc_init(); |
| 290 | - __ubuf__ uint8_t output_local[BUFFER_ELEMENTS], input_local[BUFFER_ELEMENTS]; | 296 | + __ubuf__ uint8_t output_local[BUFFER_STORAGE_ELEMENTS], input_local[BUFFER_STORAGE_ELEMENTS]; |
| 297 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 291 | asc_copy_gm2ub_align(input_local, input, BUFFER_BYTES); | 298 | asc_copy_gm2ub_align(input_local, input, BUFFER_BYTES); |
| 292 | 299 | ||
| 293 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 300 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 294 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | ||
| 295 | 301 | ||
| 296 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 302 | + |
| 297 | - uint16_t repeat_time = ceil_division(BUFFER_ELEMENTS, one_repeat_size); | 303 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 304 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); | ||
| 305 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 298 | asc_vf_call<asc_loadalign_vf>(output_local, input_local, one_repeat_size, repeat_time); | 306 | asc_vf_call<asc_loadalign_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 299 | 307 | ||
| 300 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 308 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 301 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 309 | + |
| 310 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 302 | 311 | ||
| 303 | asc_copy_ub2gm_align(output, output_local, BUFFER_BYTES); | 312 | asc_copy_ub2gm_align(output, output_local, BUFFER_BYTES); |
| 313 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 304 | asc_sync(); | 314 | asc_sync(); |
| 305 | } | 315 | } |
| 306 | } // namespace | 316 | } // namespace |
| @@ -172,26 +172,34 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 172 | #include <iostream> | 172 | #include <iostream> |
| 173 | #include <vector> | 173 | #include <vector> |
| 174 | #include "c_api/asc_simd.h" | 174 | #include "c_api/asc_simd.h" |
| 175 | +#include "utils/std/cmath.h" | ||
| 175 | #include "acl/acl.h" | 176 | #include "acl/acl.h" |
| 176 | 177 | ||
| 177 | namespace { | 178 | namespace { |
| 178 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 179 | +constexpr uint8_t MUTEX_ID = 0; |
| 179 | -{ | ||
| 180 | - return (numerator + denominator - 1) / denominator; | ||
| 181 | -} | ||
| 182 | 180 | ||
| 183 | -constexpr uint32_t INPUT_ELEMENTS = 64; | 181 | +constexpr uint32_t OUTPUT_ELEMENTS = 517; |
| 184 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 182 | +constexpr uint32_t INPUT_ELEMENTS = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, 256) * 32; |
| 185 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 183 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); |
| 186 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 184 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 185 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 186 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 187 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 188 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 189 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 32; | ||
| 187 | 190 | ||
| 191 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 192 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 193 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 188 | __simd_vf__ inline void asc_loadalign_brc_datablock_vf(__ubuf__ uint8_t* output, | 194 | __simd_vf__ inline void asc_loadalign_brc_datablock_vf(__ubuf__ uint8_t* output, |
| 189 | __ubuf__ uint8_t* input, | 195 | __ubuf__ uint8_t* input, |
| 190 | - uint16_t one_repeat_size, uint16_t repeat_time) | 196 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 191 | { | 197 | { |
| 192 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 198 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 199 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 193 | vector_uint8_t dst_reg; | 200 | vector_uint8_t dst_reg; |
| 194 | for (uint16_t i = 0; i < repeat_time; ++i) { | 201 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 202 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 195 | asc_loadalign_brc_datablock(dst_reg, input + i * 32); | 203 | asc_loadalign_brc_datablock(dst_reg, input + i * 32); |
| 196 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 204 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 197 | } | 205 | } |
| @@ -200,17 +208,21 @@ __simd_vf__ inline void asc_loadalign_brc_datablock_vf(__ubuf__ uint8_t* output, | |||
| 200 | __global__ __vector__ void asc_loadalign_brc_datablock_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 208 | __global__ __vector__ void asc_loadalign_brc_datablock_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 201 | { | 209 | { |
| 202 | asc_init(); | 210 | asc_init(); |
| 203 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 211 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 204 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 212 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 213 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 205 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 214 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 206 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 215 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 207 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 216 | + |
| 208 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 217 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 209 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 218 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 219 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 210 | asc_vf_call<asc_loadalign_brc_datablock_vf>(output_local, input_local, one_repeat_size, repeat_time); | 220 | asc_vf_call<asc_loadalign_brc_datablock_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 211 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 221 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 212 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 222 | + |
| 223 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 213 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 224 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 225 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 214 | asc_sync(); | 226 | asc_sync(); |
| 215 | } | 227 | } |
| 216 | } // namespace | 228 | } // namespace |
| @@ -97,27 +97,35 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 97 | #include <iostream> | 97 | #include <iostream> |
| 98 | #include <vector> | 98 | #include <vector> |
| 99 | #include "c_api/asc_simd.h" | 99 | #include "c_api/asc_simd.h" |
| 100 | +#include "utils/std/cmath.h" | ||
| 100 | #include "acl/acl.h" | 101 | #include "acl/acl.h" |
| 101 | 102 | ||
| 102 | namespace { | 103 | namespace { |
| 103 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 104 | +constexpr uint8_t MUTEX_ID = 0; |
| 104 | -{ | ||
| 105 | - return (numerator + denominator - 1) / denominator; | ||
| 106 | -} | ||
| 107 | 105 | ||
| 108 | -constexpr uint32_t INPUT_ELEMENTS = 64; | 106 | +constexpr uint32_t OUTPUT_ELEMENTS = 517; |
| 109 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 107 | +constexpr uint32_t INPUT_ELEMENTS = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, 256) * 32; |
| 110 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 108 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); |
| 111 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 109 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 110 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 111 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 112 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 113 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 114 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 32; | ||
| 112 | 115 | ||
| 116 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 117 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 118 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 113 | __simd_vf__ inline void asc_loadalign_brc_datablock_postupdate_vf(__ubuf__ uint8_t* output, | 119 | __simd_vf__ inline void asc_loadalign_brc_datablock_postupdate_vf(__ubuf__ uint8_t* output, |
| 114 | __ubuf__ uint8_t* input, | 120 | __ubuf__ uint8_t* input, |
| 115 | - uint16_t one_repeat_size, uint16_t repeat_time) | 121 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 116 | { | 122 | { |
| 117 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 123 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 124 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 118 | vector_uint8_t dst_reg; | 125 | vector_uint8_t dst_reg; |
| 119 | __ubuf__ uint8_t* src = input; | 126 | __ubuf__ uint8_t* src = input; |
| 120 | for (uint16_t i = 0; i < repeat_time; ++i) { | 127 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 128 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 121 | asc_loadalign_brc_datablock_postupdate(dst_reg, src, 32); | 129 | asc_loadalign_brc_datablock_postupdate(dst_reg, src, 32); |
| 122 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 130 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 123 | } | 131 | } |
| @@ -126,17 +134,21 @@ __simd_vf__ inline void asc_loadalign_brc_datablock_postupdate_vf(__ubuf__ uint8 | |||
| 126 | __global__ __vector__ void asc_loadalign_brc_datablock_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 134 | __global__ __vector__ void asc_loadalign_brc_datablock_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 127 | { | 135 | { |
| 128 | asc_init(); | 136 | asc_init(); |
| 129 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 137 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 130 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 138 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 139 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 131 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 140 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 132 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 141 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 133 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 142 | + |
| 134 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 143 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 135 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 144 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 145 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 136 | asc_vf_call<asc_loadalign_brc_datablock_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); | 146 | asc_vf_call<asc_loadalign_brc_datablock_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 137 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 147 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 138 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 148 | + |
| 149 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 139 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 150 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 151 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 140 | asc_sync(); | 152 | asc_sync(); |
| 141 | } | 153 | } |
| 142 | } // namespace | 154 | } // namespace |
| @@ -176,25 +176,32 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 176 | #include <iostream> | 176 | #include <iostream> |
| 177 | #include <vector> | 177 | #include <vector> |
| 178 | #include "c_api/asc_simd.h" | 178 | #include "c_api/asc_simd.h" |
| 179 | +#include "utils/std/cmath.h" | ||
| 179 | #include "acl/acl.h" | 180 | #include "acl/acl.h" |
| 180 | 181 | ||
| 181 | namespace { | 182 | namespace { |
| 182 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 183 | +constexpr uint8_t MUTEX_ID = 0; |
| 183 | -{ | ||
| 184 | - return (numerator + denominator - 1) / denominator; | ||
| 185 | -} | ||
| 186 | 184 | ||
| 187 | -constexpr uint32_t INPUT_ELEMENTS = 512; | 185 | +constexpr uint32_t OUTPUT_ELEMENTS = 517; |
| 188 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 186 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; |
| 187 | +constexpr uint32_t REPEAT_TIME = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 188 | +constexpr uint32_t INPUT_ELEMENTS = REPEAT_TIME; | ||
| 189 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 189 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); |
| 190 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 190 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 191 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_TIME * ELEMENTS_PER_REGISTER; | ||
| 192 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_TIME; | ||
| 191 | 193 | ||
| 194 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 195 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 196 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 192 | __simd_vf__ inline void asc_loadalign_brc_elem_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, | 197 | __simd_vf__ inline void asc_loadalign_brc_elem_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, |
| 193 | - uint16_t one_repeat_size, uint16_t repeat_time) | 198 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 194 | { | 199 | { |
| 195 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 200 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 201 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 196 | vector_uint8_t dst_reg; | 202 | vector_uint8_t dst_reg; |
| 197 | for (uint16_t i = 0; i < repeat_time; ++i) { | 203 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 204 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 198 | asc_loadalign_brc_elem(dst_reg, input + i); | 205 | asc_loadalign_brc_elem(dst_reg, input + i); |
| 199 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 206 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 200 | } | 207 | } |
| @@ -203,17 +210,21 @@ __simd_vf__ inline void asc_loadalign_brc_elem_vf(__ubuf__ uint8_t* output, __ub | |||
| 203 | __global__ __vector__ void asc_loadalign_brc_elem_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 210 | __global__ __vector__ void asc_loadalign_brc_elem_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 204 | { | 211 | { |
| 205 | asc_init(); | 212 | asc_init(); |
| 206 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 213 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 207 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 214 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 215 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 208 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 216 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
🟡 Medium Priority 变更链:本 diff 把 kernel 中的 UB 数组声明由 建议:将搬入尺寸改为与 UB 缓冲区一致:把 kernel 中 ![]() ![]() 不准确? | |||
| 209 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 217 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 210 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 218 | + |
| 211 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 219 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 212 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 220 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 221 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 213 | asc_vf_call<asc_loadalign_brc_elem_vf>(output_local, input_local, one_repeat_size, repeat_time); | 222 | asc_vf_call<asc_loadalign_brc_elem_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 214 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 223 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 215 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 224 | + |
| 225 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 216 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 226 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 227 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 217 | asc_sync(); | 228 | asc_sync(); |
| 218 | } | 229 | } |
| 219 | } // namespace | 230 | } // namespace |
| @@ -172,25 +172,33 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 172 | #include <iostream> | 172 | #include <iostream> |
| 173 | #include <vector> | 173 | #include <vector> |
| 174 | #include "c_api/asc_simd.h" | 174 | #include "c_api/asc_simd.h" |
| 175 | +#include "utils/std/cmath.h" | ||
| 175 | #include "acl/acl.h" | 176 | #include "acl/acl.h" |
| 176 | 177 | ||
| 177 | namespace { | 178 | namespace { |
| 178 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 179 | +constexpr uint8_t MUTEX_ID = 0; |
| 179 | -{ | ||
| 180 | - return (numerator + denominator - 1) / denominator; | ||
| 181 | -} | ||
| 182 | 180 | ||
| 183 | -constexpr uint32_t INPUT_ELEMENTS = 16; | 181 | +constexpr uint32_t OUTPUT_ELEMENTS = 260; |
| 184 | -constexpr uint32_t OUTPUT_ELEMENTS = 256; | 182 | +constexpr uint32_t INPUT_ELEMENTS = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, 128) * 8; |
| 185 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint16_t); | 183 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint16_t); |
| 186 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint16_t); | 184 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint16_t); |
| 185 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 128; | ||
| 186 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 187 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 188 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 189 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 8; | ||
| 187 | 190 | ||
| 191 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 192 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 193 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint16_t); | ||
| 188 | __simd_vf__ inline void asc_loadalign_brc_elem2datablock_vf( | 194 | __simd_vf__ inline void asc_loadalign_brc_elem2datablock_vf( |
| 189 | - __ubuf__ uint16_t* output, __ubuf__ uint16_t* input, uint16_t one_repeat_size, uint16_t repeat_time) | 195 | + __ubuf__ uint16_t* output, __ubuf__ uint16_t* input, uint32_t one_repeat_size, uint16_t repeat_time) |
| 190 | { | 196 | { |
| 191 | - vector_bool mask = asc_create_mask_b16(PAT_ALL); | 197 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 198 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 192 | vector_uint16_t dst_reg; | 199 | vector_uint16_t dst_reg; |
| 193 | for (uint16_t i = 0; i < repeat_time; ++i) { | 200 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 201 | + vector_bool mask = asc_update_mask_b16(remaining_length); | ||
| 194 | asc_loadalign_brc_elem2datablock(dst_reg, input + i * 8); | 202 | asc_loadalign_brc_elem2datablock(dst_reg, input + i * 8); |
| 195 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 203 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 196 | } | 204 | } |
| @@ -200,17 +208,21 @@ __global__ __vector__ void asc_loadalign_brc_elem2datablock_kernel( | |||
| 200 | __gm__ uint16_t* output, __gm__ uint16_t* input) | 208 | __gm__ uint16_t* output, __gm__ uint16_t* input) |
| 201 | { | 209 | { |
| 202 | asc_init(); | 210 | asc_init(); |
| 203 | - __ubuf__ uint16_t input_local[INPUT_ELEMENTS]; | 211 | + __ubuf__ uint16_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 204 | - __ubuf__ uint16_t output_local[OUTPUT_ELEMENTS]; | 212 | + __ubuf__ uint16_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 213 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 205 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 214 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 206 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 215 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 207 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 216 | + |
| 208 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint16_t); | 217 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint16_t)); |
| 209 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 218 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 219 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 210 | asc_vf_call<asc_loadalign_brc_elem2datablock_vf>(output_local, input_local, one_repeat_size, repeat_time); | 220 | asc_vf_call<asc_loadalign_brc_elem2datablock_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 211 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 221 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 212 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 222 | + |
| 223 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 213 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 224 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 225 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 214 | asc_sync(); | 226 | asc_sync(); |
| 215 | } | 227 | } |
| 216 | } // namespace | 228 | } // namespace |
| @@ -95,26 +95,34 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 95 | #include <iostream> | 95 | #include <iostream> |
| 96 | #include <vector> | 96 | #include <vector> |
| 97 | #include "c_api/asc_simd.h" | 97 | #include "c_api/asc_simd.h" |
| 98 | +#include "utils/std/cmath.h" | ||
| 98 | #include "acl/acl.h" | 99 | #include "acl/acl.h" |
| 99 | 100 | ||
| 100 | namespace { | 101 | namespace { |
| 101 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 102 | +constexpr uint8_t MUTEX_ID = 0; |
| 102 | -{ | ||
| 103 | - return (numerator + denominator - 1) / denominator; | ||
| 104 | -} | ||
| 105 | 103 | ||
| 106 | -constexpr uint32_t INPUT_ELEMENTS = 16; | 104 | +constexpr uint32_t OUTPUT_ELEMENTS = 260; |
| 107 | -constexpr uint32_t OUTPUT_ELEMENTS = 256; | 105 | +constexpr uint32_t INPUT_ELEMENTS = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, 128) * 8; |
| 108 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint16_t); | 106 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint16_t); |
| 109 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint16_t); | 107 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint16_t); |
| 108 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 128; | ||
| 109 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 110 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 111 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 112 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 8; | ||
| 110 | 113 | ||
| 114 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 115 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 116 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint16_t); | ||
| 111 | __simd_vf__ inline void asc_loadalign_brc_elem2datablock_postupdate_vf( | 117 | __simd_vf__ inline void asc_loadalign_brc_elem2datablock_postupdate_vf( |
| 112 | - __ubuf__ uint16_t* output, __ubuf__ uint16_t* input, uint16_t one_repeat_size, uint16_t repeat_time) | 118 | + __ubuf__ uint16_t* output, __ubuf__ uint16_t* input, uint32_t one_repeat_size, uint16_t repeat_time) |
| 113 | { | 119 | { |
| 114 | - vector_bool mask = asc_create_mask_b16(PAT_ALL); | 120 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 121 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 115 | vector_uint16_t dst_reg; | 122 | vector_uint16_t dst_reg; |
| 116 | __ubuf__ uint16_t* src = input; | 123 | __ubuf__ uint16_t* src = input; |
| 117 | for (uint16_t i = 0; i < repeat_time; ++i) { | 124 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 125 | + vector_bool mask = asc_update_mask_b16(remaining_length); | ||
| 118 | asc_loadalign_brc_elem2datablock_postupdate(dst_reg, src, 8); | 126 | asc_loadalign_brc_elem2datablock_postupdate(dst_reg, src, 8); |
| 119 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 127 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 120 | } | 128 | } |
| @@ -124,17 +132,21 @@ __global__ __vector__ void asc_loadalign_brc_elem2datablock_postupdate_kernel( | |||
| 124 | __gm__ uint16_t* output, __gm__ uint16_t* input) | 132 | __gm__ uint16_t* output, __gm__ uint16_t* input) |
| 125 | { | 133 | { |
| 126 | asc_init(); | 134 | asc_init(); |
| 127 | - __ubuf__ uint16_t input_local[INPUT_ELEMENTS]; | 135 | + __ubuf__ uint16_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 128 | - __ubuf__ uint16_t output_local[OUTPUT_ELEMENTS]; | 136 | + __ubuf__ uint16_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 137 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 129 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 138 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 130 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 139 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 131 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 140 | + |
| 132 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint16_t); | 141 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint16_t)); |
| 133 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 142 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 143 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 134 | asc_vf_call<asc_loadalign_brc_elem2datablock_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); | 144 | asc_vf_call<asc_loadalign_brc_elem2datablock_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 135 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 145 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 136 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 146 | + |
| 147 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 137 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 148 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 149 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 138 | asc_sync(); | 150 | asc_sync(); |
| 139 | } | 151 | } |
| 140 | } // namespace | 152 | } // namespace |
| @@ -101,27 +101,35 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 101 | #include <iostream> | 101 | #include <iostream> |
| 102 | #include <vector> | 102 | #include <vector> |
| 103 | #include "c_api/asc_simd.h" | 103 | #include "c_api/asc_simd.h" |
| 104 | +#include "utils/std/cmath.h" | ||
| 104 | #include "acl/acl.h" | 105 | #include "acl/acl.h" |
| 105 | 106 | ||
| 106 | namespace { | 107 | namespace { |
| 107 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 108 | +constexpr uint8_t MUTEX_ID = 0; |
| 108 | -{ | ||
| 109 | - return (numerator + denominator - 1) / denominator; | ||
| 110 | -} | ||
| 111 | 109 | ||
| 112 | -constexpr uint32_t INPUT_ELEMENTS = 2; | 110 | +constexpr uint32_t OUTPUT_ELEMENTS = 517; |
| 113 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 111 | +constexpr uint32_t INPUT_ELEMENTS = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, 256); |
| 114 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 112 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); |
| 115 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 113 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 114 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 115 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 116 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 117 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 118 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 1; | ||
| 116 | 119 | ||
| 120 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 121 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 122 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 117 | __simd_vf__ inline void asc_loadalign_brc_elem_postupdate_vf(__ubuf__ uint8_t* output, | 123 | __simd_vf__ inline void asc_loadalign_brc_elem_postupdate_vf(__ubuf__ uint8_t* output, |
| 118 | __ubuf__ uint8_t* input, | 124 | __ubuf__ uint8_t* input, |
| 119 | - uint16_t one_repeat_size, uint16_t repeat_time) | 125 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 120 | { | 126 | { |
| 121 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 127 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 128 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 122 | vector_uint8_t dst_reg; | 129 | vector_uint8_t dst_reg; |
| 123 | __ubuf__ uint8_t* src = input; | 130 | __ubuf__ uint8_t* src = input; |
| 124 | for (uint16_t i = 0; i < repeat_time; ++i) { | 131 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 132 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 125 | asc_loadalign_brc_elem_postupdate(dst_reg, src, 1); | 133 | asc_loadalign_brc_elem_postupdate(dst_reg, src, 1); |
| 126 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 134 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 127 | } | 135 | } |
| @@ -130,17 +138,21 @@ __simd_vf__ inline void asc_loadalign_brc_elem_postupdate_vf(__ubuf__ uint8_t* o | |||
| 130 | __global__ __vector__ void asc_loadalign_brc_elem_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 138 | __global__ __vector__ void asc_loadalign_brc_elem_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 131 | { | 139 | { |
| 132 | asc_init(); | 140 | asc_init(); |
| 133 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 141 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 134 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 142 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 143 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 135 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 144 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 136 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 145 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 137 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 146 | + |
| 138 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 147 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 139 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 148 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 149 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 140 | asc_vf_call<asc_loadalign_brc_elem_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); | 150 | asc_vf_call<asc_loadalign_brc_elem_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 141 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 151 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 142 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 152 | + |
| 153 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 143 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 154 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 155 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 144 | asc_sync(); | 156 | asc_sync(); |
| 145 | } | 157 | } |
| 146 | } // namespace | 158 | } // namespace |
| @@ -98,22 +98,43 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 98 | #include <iostream> | 98 | #include <iostream> |
| 99 | #include <vector> | 99 | #include <vector> |
| 100 | #include "c_api/asc_simd.h" | 100 | #include "c_api/asc_simd.h" |
| 101 | +#include "utils/std/cmath.h" | ||
| 101 | #include "acl/acl.h" | 102 | #include "acl/acl.h" |
| 102 | 103 | ||
| 103 | namespace { | 104 | namespace { |
| 105 | + | ||
| 104 | constexpr uint32_t DATABLOCK_BYTES = 32; | 106 | constexpr uint32_t DATABLOCK_BYTES = 32; |
| 105 | -constexpr uint32_t DATABLOCK_COUNT = 8; | 107 | +constexpr uint32_t DATABLOCKS_PER_REGISTER = 8; |
| 108 | +constexpr uint32_t DATABLOCK_COUNT = 11; | ||
| 106 | constexpr uint16_t BLOCK_STRIDE = 2; | 109 | constexpr uint16_t BLOCK_STRIDE = 2; |
| 107 | -constexpr uint16_t REPEAT_STRIDE = 1; | 110 | +constexpr uint16_t REPEAT_STRIDE = 0; |
| 108 | -constexpr uint32_t INPUT_BYTES = 16 * DATABLOCK_BYTES; | 111 | +constexpr uint32_t START_BLOCK = 1; |
| 109 | -constexpr uint32_t OUTPUT_BYTES = DATABLOCK_COUNT * DATABLOCK_BYTES; | 112 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 |
| 113 | +constexpr uint32_t REPEAT_COUNT = | ||
| 114 | + (DATABLOCK_COUNT + DATABLOCKS_PER_REGISTER - 1) / DATABLOCKS_PER_REGISTER; | ||
| 115 | +constexpr uint32_t INPUT_BYTES_PER_REPEAT = 16 * DATABLOCK_BYTES; | ||
| 116 | +constexpr uint32_t OUTPUT_BYTES_PER_REPEAT = DATABLOCKS_PER_REGISTER * DATABLOCK_BYTES; | ||
| 117 | +constexpr uint32_t INPUT_BYTES = INPUT_BYTES_PER_REPEAT * REPEAT_COUNT; | ||
| 118 | +constexpr uint32_t OUTPUT_BYTES = OUTPUT_BYTES_PER_REPEAT * REPEAT_COUNT; | ||
| 119 | + | ||
| 120 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 121 | +constexpr uint32_t TOTAL_LENGTH = DATABLOCK_COUNT; | ||
| 122 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * DATABLOCK_BYTES; | ||
| 123 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 110 | 124 | ||
| 111 | __simd_vf__ inline void asc_loadalign_datablock_strided_vf( | 125 | __simd_vf__ inline void asc_loadalign_datablock_strided_vf( |
| 112 | - __ubuf__ uint8_t* output, __ubuf__ uint8_t* input) | 126 | + __ubuf__ uint8_t* output, __ubuf__ uint8_t* input, uint32_t one_repeat_size, uint16_t repeat_time) |
| 113 | { | 127 | { |
| 114 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 128 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 115 | - vector_uint8_t dst = asc_loadalign_datablock_strided(input, BLOCK_STRIDE, REPEAT_STRIDE, mask); | 129 | + uint32_t remaining_length = DATABLOCK_COUNT * DATABLOCK_BYTES; |
| 116 | - asc_storealign(output, dst, mask); | 130 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 131 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 132 | + const uint32_t input_offset = i * INPUT_BYTES_PER_REPEAT; | ||
| 133 | + const uint32_t output_offset = i * OUTPUT_BYTES_PER_REPEAT; | ||
| 134 | + // 起始块偏移通过指针指定,repeat_stride不是本次读取的起始偏移。 | ||
| 135 | + vector_uint8_t dst = asc_loadalign_datablock_strided(input + input_offset + START_BLOCK * DATABLOCK_BYTES, BLOCK_STRIDE, REPEAT_STRIDE, mask); | ||
| 136 | + asc_storealign(output + output_offset, dst, mask); | ||
| 137 | + } | ||
| 117 | } | 138 | } |
| 118 | 139 | ||
| 119 | __global__ __vector__ void asc_loadalign_datablock_strided_kernel( | 140 | __global__ __vector__ void asc_loadalign_datablock_strided_kernel( |
| @@ -122,13 +143,20 @@ __global__ __vector__ void asc_loadalign_datablock_strided_kernel( | |||
| 122 | asc_init(); | 143 | asc_init(); |
| 123 | __ubuf__ uint8_t input_local[INPUT_BYTES]; | 144 | __ubuf__ uint8_t input_local[INPUT_BYTES]; |
| 124 | __ubuf__ uint8_t output_local[OUTPUT_BYTES]; | 145 | __ubuf__ uint8_t output_local[OUTPUT_BYTES]; |
| 146 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 125 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 147 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 126 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 148 | + asc_copy_gm2ub_align(output_local, output, OUTPUT_BYTES); |
| 127 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 149 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 128 | - asc_vf_call<asc_loadalign_datablock_strided_vf>(output_local, input_local); | 150 | + |
| 129 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 151 | + uint32_t one_repeat_size = asc_get_vf_len() / DATABLOCK_BYTES; |
| 130 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 152 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 153 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 154 | + asc_vf_call<asc_loadalign_datablock_strided_vf>(output_local, input_local, one_repeat_size, repeat_time); | ||
| 155 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 156 | + | ||
| 157 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 131 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 158 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 159 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 132 | asc_sync(); | 160 | asc_sync(); |
| 133 | } | 161 | } |
| 134 | } // namespace | 162 | } // namespace |
| @@ -136,14 +164,20 @@ __global__ __vector__ void asc_loadalign_datablock_strided_kernel( | |||
| 136 | int main() | 164 | int main() |
| 137 | { | 165 | { |
| 138 | std::vector<uint8_t> input(INPUT_BYTES); | 166 | std::vector<uint8_t> input(INPUT_BYTES); |
| 139 | - std::vector<uint8_t> output(OUTPUT_BYTES, 0xff); | 167 | + std::vector<uint8_t> output(OUTPUT_BYTES, 0); |
| 140 | std::vector<uint8_t> golden(OUTPUT_BYTES, 0); | 168 | std::vector<uint8_t> golden(OUTPUT_BYTES, 0); |
| 141 | for (uint32_t i = 0; i < INPUT_BYTES; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); | 169 | for (uint32_t i = 0; i < INPUT_BYTES; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); |
| 142 | - for (uint32_t block = 0; block < DATABLOCK_COUNT; ++block) { | 170 | + for (uint32_t repeat = 0; repeat < REPEAT_COUNT; ++repeat) { |
| 143 | - const uint32_t src_offset = (REPEAT_STRIDE + block * BLOCK_STRIDE) * DATABLOCK_BYTES; | 171 | + const uint32_t input_base = repeat * INPUT_BYTES_PER_REPEAT; |
| 144 | - const uint32_t dst_offset = block * DATABLOCK_BYTES; | 172 | + const uint32_t output_base = repeat * OUTPUT_BYTES_PER_REPEAT; |
| 145 | - for (uint32_t i = 0; i < DATABLOCK_BYTES; ++i) { | 173 | + const uint32_t valid_blocks = repeat + 1 == REPEAT_COUNT ? |
| 146 | - golden[dst_offset + i] = input[src_offset + i]; | 174 | + DATABLOCK_COUNT - repeat * DATABLOCKS_PER_REGISTER : DATABLOCKS_PER_REGISTER; |
| 175 | + for (uint32_t block = 0; block < valid_blocks; ++block) { | ||
| 176 | + const uint32_t src_offset = input_base + (START_BLOCK + block * BLOCK_STRIDE) * DATABLOCK_BYTES; | ||
| 177 | + const uint32_t dst_offset = output_base + block * DATABLOCK_BYTES; | ||
| 178 | + for (uint32_t i = 0; i < DATABLOCK_BYTES; ++i) { | ||
| 179 | + golden[dst_offset + i] = input[src_offset + i]; | ||
| 180 | + } | ||
| 147 | } | 181 | } |
| 148 | } | 182 | } |
| 149 | 183 | ||
| @@ -154,6 +188,7 @@ int main() | |||
| 154 | aclrtMalloc(reinterpret_cast<void**>(&input_device), INPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 188 | aclrtMalloc(reinterpret_cast<void**>(&input_device), INPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); |
| 155 | aclrtMalloc(reinterpret_cast<void**>(&output_device), OUTPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 189 | aclrtMalloc(reinterpret_cast<void**>(&output_device), OUTPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); |
| 156 | aclrtMemcpy(input_device, INPUT_BYTES, input.data(), INPUT_BYTES, ACL_MEMCPY_HOST_TO_DEVICE); | 190 | aclrtMemcpy(input_device, INPUT_BYTES, input.data(), INPUT_BYTES, ACL_MEMCPY_HOST_TO_DEVICE); |
| 191 | + aclrtMemcpy(output_device, OUTPUT_BYTES, output.data(), OUTPUT_BYTES, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 157 | asc_loadalign_datablock_strided_kernel<<<1, 0>>>(output_device, input_device); | 192 | asc_loadalign_datablock_strided_kernel<<<1, 0>>>(output_device, input_device); |
| 158 | aclrtSynchronizeDevice(); | 193 | aclrtSynchronizeDevice(); |
| 159 | aclrtMemcpy(output.data(), OUTPUT_BYTES, output_device, OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); | 194 | aclrtMemcpy(output.data(), OUTPUT_BYTES, output_device, OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); |
| @@ -176,61 +176,76 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 176 | #include <iostream> | 176 | #include <iostream> |
| 177 | #include <vector> | 177 | #include <vector> |
| 178 | #include "c_api/asc_simd.h" | 178 | #include "c_api/asc_simd.h" |
| 179 | +#include "utils/std/cmath.h" | ||
| 179 | #include "acl/acl.h" | 180 | #include "acl/acl.h" |
| 180 | 181 | ||
| 181 | namespace { | 182 | namespace { |
| 182 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 183 | +constexpr uint8_t MUTEX_ID = 0; |
| 183 | -{ | ||
| 184 | - return (numerator + denominator - 1) / denominator; | ||
| 185 | -} | ||
| 186 | 184 | ||
| 187 | -constexpr uint32_t INPUT_ELEMENTS = 1024; | 185 | +constexpr uint32_t INPUT_ELEMENTS = 1030; |
| 188 | -constexpr uint32_t OUTPUT_ELEMENTS = 1024; | 186 | +constexpr uint32_t OUTPUT_ELEMENTS = 1030; |
| 189 | -constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 187 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; |
| 190 | -constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 188 | +constexpr uint32_t PAIR_COUNT = (OUTPUT_ELEMENTS + 1) / 2; |
| 189 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 190 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(PAIR_COUNT, ELEMENTS_PER_REGISTER); | ||
| 191 | +constexpr uint32_t STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER * 2; | ||
| 192 | +constexpr uint32_t INPUT_BYTES = STORAGE_ELEMENTS * sizeof(uint8_t); | ||
| 193 | +constexpr uint32_t OUTPUT_BYTES = STORAGE_ELEMENTS * sizeof(uint8_t); | ||
| 191 | 194 | ||
| 195 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 196 | +constexpr uint32_t TOTAL_LENGTH = PAIR_COUNT; | ||
| 197 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 192 | __simd_vf__ inline void asc_loadalign_deintlv_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, | 198 | __simd_vf__ inline void asc_loadalign_deintlv_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, |
| 193 | - uint16_t one_repeat_size, uint16_t repeat_time) | 199 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 194 | { | 200 | { |
| 195 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | ||
| 196 | vector_uint8_t even_reg; | 201 | vector_uint8_t even_reg; |
| 197 | vector_uint8_t odd_reg; | 202 | vector_uint8_t odd_reg; |
| 203 | + uint32_t remaining_length_even = (OUTPUT_ELEMENTS + 1) / 2; | ||
| 204 | + uint32_t remaining_length_odd = OUTPUT_ELEMENTS / 2; | ||
| 198 | for (uint16_t i = 0; i < repeat_time; ++i) { | 205 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 206 | + vector_bool even_mask = asc_update_mask_b8(remaining_length_even); | ||
| 207 | + vector_bool odd_mask = asc_update_mask_b8(remaining_length_odd); | ||
| 199 | asc_loadalign_deintlv(even_reg, odd_reg, input + i * 512); | 208 | asc_loadalign_deintlv(even_reg, odd_reg, input + i * 512); |
| 200 | - asc_storealign(output + i * 512, even_reg, mask); | 209 | + asc_storealign(output + i * 512, even_reg, even_mask); |
| 201 | - asc_storealign(output + i * 512 + one_repeat_size, odd_reg, mask); | 210 | + asc_storealign(output + i * 512 + one_repeat_size, odd_reg, odd_mask); |
| 202 | } | 211 | } |
| 203 | } | 212 | } |
| 204 | 213 | ||
| 205 | __global__ __vector__ void asc_loadalign_deintlv_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 214 | __global__ __vector__ void asc_loadalign_deintlv_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 206 | { | 215 | { |
| 207 | asc_init(); | 216 | asc_init(); |
| 208 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 217 | + __ubuf__ uint8_t input_local[STORAGE_ELEMENTS]; |
| 209 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 218 | + __ubuf__ uint8_t output_local[STORAGE_ELEMENTS]; |
| 219 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 210 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 220 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 211 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 221 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 212 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 222 | + |
| 213 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 223 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 214 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS / 2, one_repeat_size); | 224 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 225 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 215 | asc_vf_call<asc_loadalign_deintlv_vf>(output_local, input_local, one_repeat_size, repeat_time); | 226 | asc_vf_call<asc_loadalign_deintlv_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 216 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 227 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 217 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 228 | + |
| 229 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 218 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 230 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 231 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 219 | asc_sync(); | 232 | asc_sync(); |
| 220 | } | 233 | } |
| 221 | } // namespace | 234 | } // namespace |
| 222 | 235 | ||
| 223 | int main() | 236 | int main() |
| 224 | { | 237 | { |
| 225 | - std::vector<uint8_t> input(INPUT_ELEMENTS); | 238 | + std::vector<uint8_t> input(STORAGE_ELEMENTS, 0); |
| 226 | - std::vector<uint8_t> output(OUTPUT_ELEMENTS, 0xff); | 239 | + std::vector<uint8_t> output(STORAGE_ELEMENTS, 0xff); |
| 227 | - std::vector<uint8_t> golden(OUTPUT_ELEMENTS, 0); | 240 | + std::vector<uint8_t> golden(STORAGE_ELEMENTS, 0xff); |
| 228 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); | 241 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); |
| 229 | - for (uint16_t i = 0; i < OUTPUT_ELEMENTS / 2; ++i) { | 242 | + for (uint32_t i = 0; i < PAIR_COUNT; ++i) { |
| 230 | - const uint16_t repeat = i / 256; | 243 | + const uint32_t repeat = i / ELEMENTS_PER_REGISTER; |
| 231 | - const uint16_t offset = i % 256; | 244 | + const uint32_t offset = i % ELEMENTS_PER_REGISTER; |
| 232 | golden[repeat * 512 + offset] = input[repeat * 512 + 2 * offset]; | 245 | golden[repeat * 512 + offset] = input[repeat * 512 + 2 * offset]; |
| 233 | - golden[repeat * 512 + 256 + offset] = input[repeat * 512 + 2 * offset + 1]; | 246 | + if (2 * i + 1 < OUTPUT_ELEMENTS) { |
| 247 | + golden[repeat * 512 + ELEMENTS_PER_REGISTER + offset] = input[repeat * 512 + 2 * offset + 1]; | ||
| 248 | + } | ||
| 234 | } | 249 | } |
| 235 | 250 | ||
| 236 | aclInit(nullptr); | 251 | aclInit(nullptr); |
| @@ -244,7 +259,16 @@ int main() | |||
| 244 | aclrtSynchronizeDevice(); | 259 | aclrtSynchronizeDevice(); |
| 245 | aclrtMemcpy(output.data(), OUTPUT_BYTES, output_device, OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); | 260 | aclrtMemcpy(output.data(), OUTPUT_BYTES, output_device, OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); |
| 246 | 261 | ||
| 247 | - const bool passed = output == golden; | 262 | + bool passed = true; |
| 263 | + for (uint32_t i = 0; i < PAIR_COUNT; ++i) { | ||
| 264 | + const uint32_t repeat = i / ELEMENTS_PER_REGISTER; | ||
| 265 | + const uint32_t offset = i % ELEMENTS_PER_REGISTER; | ||
| 266 | + passed = passed && output[repeat * 512 + offset] == golden[repeat * 512 + offset]; | ||
| 267 | + if (2 * i + 1 < OUTPUT_ELEMENTS) { | ||
| 268 | + passed = passed && output[repeat * 512 + ELEMENTS_PER_REGISTER + offset] == | ||
| 269 | + golden[repeat * 512 + ELEMENTS_PER_REGISTER + offset]; | ||
| 270 | + } | ||
| 271 | + } | ||
| 248 | std::cout << (passed ? "[Success]" : "[Failed]") << " asc_loadalign_deintlv example." << std::endl; | 272 | std::cout << (passed ? "[Success]" : "[Failed]") << " asc_loadalign_deintlv example." << std::endl; |
| 249 | aclrtFree(input_device); | 273 | aclrtFree(input_device); |
| 250 | aclrtFree(output_device); | 274 | aclrtFree(output_device); |
| @@ -102,62 +102,77 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 102 | #include <iostream> | 102 | #include <iostream> |
| 103 | #include <vector> | 103 | #include <vector> |
| 104 | #include "c_api/asc_simd.h" | 104 | #include "c_api/asc_simd.h" |
| 105 | +#include "utils/std/cmath.h" | ||
| 105 | #include "acl/acl.h" | 106 | #include "acl/acl.h" |
| 106 | 107 | ||
| 107 | namespace { | 108 | namespace { |
| 108 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 109 | +constexpr uint8_t MUTEX_ID = 0; |
| 109 | -{ | ||
| 110 | - return (numerator + denominator - 1) / denominator; | ||
| 111 | -} | ||
| 112 | 110 | ||
| 113 | -constexpr uint32_t INPUT_ELEMENTS = 1024; | 111 | +constexpr uint32_t INPUT_ELEMENTS = 1030; |
| 114 | -constexpr uint32_t OUTPUT_ELEMENTS = 1024; | 112 | +constexpr uint32_t OUTPUT_ELEMENTS = 1030; |
| 115 | -constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 113 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; |
| 116 | -constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 114 | +constexpr uint32_t PAIR_COUNT = (OUTPUT_ELEMENTS + 1) / 2; |
| 115 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 116 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(PAIR_COUNT, ELEMENTS_PER_REGISTER); | ||
| 117 | +constexpr uint32_t STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER * 2; | ||
| 118 | +constexpr uint32_t INPUT_BYTES = STORAGE_ELEMENTS * sizeof(uint8_t); | ||
| 119 | +constexpr uint32_t OUTPUT_BYTES = STORAGE_ELEMENTS * sizeof(uint8_t); | ||
| 117 | 120 | ||
| 121 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 122 | +constexpr uint32_t TOTAL_LENGTH = PAIR_COUNT; | ||
| 123 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 118 | __simd_vf__ inline void asc_loadalign_deintlv_postupdate_vf(__ubuf__ uint8_t* output, | 124 | __simd_vf__ inline void asc_loadalign_deintlv_postupdate_vf(__ubuf__ uint8_t* output, |
| 119 | __ubuf__ uint8_t* input, | 125 | __ubuf__ uint8_t* input, |
| 120 | - uint16_t one_repeat_size, uint16_t repeat_time) | 126 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 121 | { | 127 | { |
| 122 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | ||
| 123 | vector_uint8_t even_reg; | 128 | vector_uint8_t even_reg; |
| 124 | vector_uint8_t odd_reg; | 129 | vector_uint8_t odd_reg; |
| 130 | + uint32_t remaining_length_even = (OUTPUT_ELEMENTS + 1) / 2; | ||
| 131 | + uint32_t remaining_length_odd = OUTPUT_ELEMENTS / 2; | ||
| 125 | for (uint16_t i = 0; i < repeat_time; ++i) { | 132 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 133 | + vector_bool even_mask = asc_update_mask_b8(remaining_length_even); | ||
| 134 | + vector_bool odd_mask = asc_update_mask_b8(remaining_length_odd); | ||
| 126 | asc_loadalign_deintlv_postupdate(even_reg, odd_reg, input, 512); | 135 | asc_loadalign_deintlv_postupdate(even_reg, odd_reg, input, 512); |
| 127 | - asc_storealign(output + i * 512, even_reg, mask); | 136 | + asc_storealign(output + i * 512, even_reg, even_mask); |
| 128 | - asc_storealign(output + i * 512 + one_repeat_size, odd_reg, mask); | 137 | + asc_storealign(output + i * 512 + one_repeat_size, odd_reg, odd_mask); |
| 129 | } | 138 | } |
| 130 | } | 139 | } |
| 131 | 140 | ||
| 132 | __global__ __vector__ void asc_loadalign_deintlv_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 141 | __global__ __vector__ void asc_loadalign_deintlv_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 133 | { | 142 | { |
| 134 | asc_init(); | 143 | asc_init(); |
| 135 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 144 | + __ubuf__ uint8_t input_local[STORAGE_ELEMENTS]; |
| 136 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 145 | + __ubuf__ uint8_t output_local[STORAGE_ELEMENTS]; |
| 146 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 137 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 147 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 138 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 148 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 139 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 149 | + |
| 140 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 150 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 141 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS / 2, one_repeat_size); | 151 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 152 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 142 | asc_vf_call<asc_loadalign_deintlv_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); | 153 | asc_vf_call<asc_loadalign_deintlv_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 143 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 154 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 144 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 155 | + |
| 156 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 145 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 157 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 158 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 146 | asc_sync(); | 159 | asc_sync(); |
| 147 | } | 160 | } |
| 148 | } // namespace | 161 | } // namespace |
| 149 | 162 | ||
| 150 | int main() | 163 | int main() |
| 151 | { | 164 | { |
| 152 | - std::vector<uint8_t> input(INPUT_ELEMENTS); | 165 | + std::vector<uint8_t> input(STORAGE_ELEMENTS, 0); |
| 153 | - std::vector<uint8_t> output(OUTPUT_ELEMENTS, 0xff); | 166 | + std::vector<uint8_t> output(STORAGE_ELEMENTS, 0xff); |
| 154 | - std::vector<uint8_t> golden(OUTPUT_ELEMENTS, 0); | 167 | + std::vector<uint8_t> golden(STORAGE_ELEMENTS, 0xff); |
| 155 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); | 168 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); |
| 156 | - for (uint16_t i = 0; i < OUTPUT_ELEMENTS / 2; ++i) { | 169 | + for (uint32_t i = 0; i < PAIR_COUNT; ++i) { |
| 157 | - const uint16_t repeat = i / 256; | 170 | + const uint32_t repeat = i / ELEMENTS_PER_REGISTER; |
| 158 | - const uint16_t offset = i % 256; | 171 | + const uint32_t offset = i % ELEMENTS_PER_REGISTER; |
| 159 | golden[repeat * 512 + offset] = input[repeat * 512 + 2 * offset]; | 172 | golden[repeat * 512 + offset] = input[repeat * 512 + 2 * offset]; |
| 160 | - golden[repeat * 512 + 256 + offset] = input[repeat * 512 + 2 * offset + 1]; | 173 | + if (2 * i + 1 < OUTPUT_ELEMENTS) { |
| 174 | + golden[repeat * 512 + ELEMENTS_PER_REGISTER + offset] = input[repeat * 512 + 2 * offset + 1]; | ||
| 175 | + } | ||
| 161 | } | 176 | } |
| 162 | 177 | ||
| 163 | aclInit(nullptr); | 178 | aclInit(nullptr); |
| @@ -171,7 +186,16 @@ int main() | |||
| 171 | aclrtSynchronizeDevice(); | 186 | aclrtSynchronizeDevice(); |
| 172 | aclrtMemcpy(output.data(), OUTPUT_BYTES, output_device, OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); | 187 | aclrtMemcpy(output.data(), OUTPUT_BYTES, output_device, OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); |
| 173 | 188 | ||
| 174 | - const bool passed = output == golden; | 189 | + bool passed = true; |
| 190 | + for (uint32_t i = 0; i < PAIR_COUNT; ++i) { | ||
| 191 | + const uint32_t repeat = i / ELEMENTS_PER_REGISTER; | ||
| 192 | + const uint32_t offset = i % ELEMENTS_PER_REGISTER; | ||
| 193 | + passed = passed && output[repeat * 512 + offset] == golden[repeat * 512 + offset]; | ||
| 194 | + if (2 * i + 1 < OUTPUT_ELEMENTS) { | ||
| 195 | + passed = passed && output[repeat * 512 + ELEMENTS_PER_REGISTER + offset] == | ||
| 196 | + golden[repeat * 512 + ELEMENTS_PER_REGISTER + offset]; | ||
| 197 | + } | ||
| 198 | + } | ||
| 175 | std::cout << (passed ? "[Success]" : "[Failed]") << " asc_loadalign_deintlv_postupdate example." << std::endl; | 199 | std::cout << (passed ? "[Success]" : "[Failed]") << " asc_loadalign_deintlv_postupdate example." << std::endl; |
| 176 | aclrtFree(input_device); | 200 | aclrtFree(input_device); |
| 177 | aclrtFree(output_device); | 201 | aclrtFree(output_device); |
| @@ -196,25 +196,33 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 196 | #include <iostream> | 196 | #include <iostream> |
| 197 | #include <vector> | 197 | #include <vector> |
| 198 | #include "c_api/asc_simd.h" | 198 | #include "c_api/asc_simd.h" |
| 199 | +#include "utils/std/cmath.h" | ||
| 199 | #include "acl/acl.h" | 200 | #include "acl/acl.h" |
| 200 | 201 | ||
| 201 | namespace { | 202 | namespace { |
| 202 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 203 | +constexpr uint8_t MUTEX_ID = 0; |
| 203 | -{ | ||
| 204 | - return (numerator + denominator - 1) / denominator; | ||
| 205 | -} | ||
| 206 | 204 | ||
| 207 | -constexpr uint32_t INPUT_ELEMENTS = 1024; | 205 | +constexpr uint32_t INPUT_ELEMENTS = 1030; |
| 208 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 206 | +constexpr uint32_t OUTPUT_ELEMENTS = 517; |
| 209 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 207 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); |
| 210 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 208 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 209 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 210 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 211 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 212 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 213 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 512; | ||
| 211 | 214 | ||
| 215 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 216 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 217 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 212 | __simd_vf__ inline void asc_loadalign_downsample_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, | 218 | __simd_vf__ inline void asc_loadalign_downsample_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, |
| 213 | - uint16_t one_repeat_size, uint16_t repeat_time) | 219 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 214 | { | 220 | { |
| 215 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 221 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 222 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 216 | vector_uint8_t dst_reg; | 223 | vector_uint8_t dst_reg; |
| 217 | for (uint16_t i = 0; i < repeat_time; ++i) { | 224 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 225 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 218 | asc_loadalign_downsample(dst_reg, input + i * 512); | 226 | asc_loadalign_downsample(dst_reg, input + i * 512); |
| 219 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 227 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 220 | } | 228 | } |
| @@ -223,24 +231,28 @@ __simd_vf__ inline void asc_loadalign_downsample_vf(__ubuf__ uint8_t* output, __ | |||
| 223 | __global__ __vector__ void asc_loadalign_downsample_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 231 | __global__ __vector__ void asc_loadalign_downsample_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 224 | { | 232 | { |
| 225 | asc_init(); | 233 | asc_init(); |
| 226 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 234 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 227 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 235 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 228 | - asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 236 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 229 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 237 | + asc_copy_gm2ub_align(input_local, input, INPUT_STORAGE_ELEMENTS); |
| 230 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 238 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 231 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 239 | + |
| 232 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 240 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 241 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); | ||
| 242 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 233 | asc_vf_call<asc_loadalign_downsample_vf>(output_local, input_local, one_repeat_size, repeat_time); | 243 | asc_vf_call<asc_loadalign_downsample_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 234 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 244 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 235 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 245 | + |
| 246 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 236 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 247 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 248 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 237 | asc_sync(); | 249 | asc_sync(); |
| 238 | } | 250 | } |
| 239 | } // namespace | 251 | } // namespace |
| 240 | 252 | ||
| 241 | int main() | 253 | int main() |
| 242 | { | 254 | { |
| 243 | - std::vector<uint8_t> input(INPUT_ELEMENTS); | 255 | + std::vector<uint8_t> input(INPUT_STORAGE_ELEMENTS, 0); |
| 244 | std::vector<uint8_t> output(OUTPUT_ELEMENTS, 0xff); | 256 | std::vector<uint8_t> output(OUTPUT_ELEMENTS, 0xff); |
| 245 | std::vector<uint8_t> golden(OUTPUT_ELEMENTS, 0); | 257 | std::vector<uint8_t> golden(OUTPUT_ELEMENTS, 0); |
| 246 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); | 258 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); |
| @@ -250,9 +262,9 @@ int main() | |||
| 250 | aclrtSetDevice(0); | 262 | aclrtSetDevice(0); |
| 251 | uint8_t* input_device = nullptr; | 263 | uint8_t* input_device = nullptr; |
| 252 | uint8_t* output_device = nullptr; | 264 | uint8_t* output_device = nullptr; |
| 253 | - aclrtMalloc(reinterpret_cast<void**>(&input_device), INPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 265 | + aclrtMalloc(reinterpret_cast<void**>(&input_device), INPUT_STORAGE_ELEMENTS, ACL_MEM_MALLOC_HUGE_FIRST); |
| 254 | aclrtMalloc(reinterpret_cast<void**>(&output_device), OUTPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 266 | aclrtMalloc(reinterpret_cast<void**>(&output_device), OUTPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); |
| 255 | - aclrtMemcpy(input_device, INPUT_BYTES, input.data(), INPUT_BYTES, ACL_MEMCPY_HOST_TO_DEVICE); | 267 | + aclrtMemcpy(input_device, INPUT_STORAGE_ELEMENTS, input.data(), INPUT_STORAGE_ELEMENTS, ACL_MEMCPY_HOST_TO_DEVICE); |
| 256 | asc_loadalign_downsample_kernel<<<1, 0>>>(output_device, input_device); | 268 | asc_loadalign_downsample_kernel<<<1, 0>>>(output_device, input_device); |
| 257 | aclrtSynchronizeDevice(); | 269 | aclrtSynchronizeDevice(); |
| 258 | aclrtMemcpy(output.data(), OUTPUT_BYTES, output_device, OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); | 270 | aclrtMemcpy(output.data(), OUTPUT_BYTES, output_device, OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); |
| @@ -107,27 +107,35 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 107 | #include <iostream> | 107 | #include <iostream> |
| 108 | #include <vector> | 108 | #include <vector> |
| 109 | #include "c_api/asc_simd.h" | 109 | #include "c_api/asc_simd.h" |
| 110 | +#include "utils/std/cmath.h" | ||
| 110 | #include "acl/acl.h" | 111 | #include "acl/acl.h" |
| 111 | 112 | ||
| 112 | namespace { | 113 | namespace { |
| 113 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 114 | +constexpr uint8_t MUTEX_ID = 0; |
| 114 | -{ | ||
| 115 | - return (numerator + denominator - 1) / denominator; | ||
| 116 | -} | ||
| 117 | 115 | ||
| 118 | -constexpr uint32_t INPUT_ELEMENTS = 1024; | 116 | +constexpr uint32_t INPUT_ELEMENTS = 1030; |
| 119 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 117 | +constexpr uint32_t OUTPUT_ELEMENTS = 517; |
| 120 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 118 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); |
| 121 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 119 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 120 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 121 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 122 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 123 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 124 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 512; | ||
| 122 | 125 | ||
| 126 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 127 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 128 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 123 | __simd_vf__ inline void asc_loadalign_downsample_postupdate_vf(__ubuf__ uint8_t* output, | 129 | __simd_vf__ inline void asc_loadalign_downsample_postupdate_vf(__ubuf__ uint8_t* output, |
| 124 | __ubuf__ uint8_t* input, | 130 | __ubuf__ uint8_t* input, |
| 125 | - uint16_t one_repeat_size, uint16_t repeat_time) | 131 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 126 | { | 132 | { |
| 127 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 133 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 134 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 128 | vector_uint8_t dst_reg; | 135 | vector_uint8_t dst_reg; |
| 129 | __ubuf__ uint8_t* src = input; | 136 | __ubuf__ uint8_t* src = input; |
| 130 | for (uint16_t i = 0; i < repeat_time; ++i) { | 137 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 138 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 131 | asc_loadalign_downsample_postupdate(dst_reg, src, 512); | 139 | asc_loadalign_downsample_postupdate(dst_reg, src, 512); |
| 132 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 140 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 133 | } | 141 | } |
| @@ -136,24 +144,28 @@ __simd_vf__ inline void asc_loadalign_downsample_postupdate_vf(__ubuf__ uint8_t* | |||
| 136 | __global__ __vector__ void asc_loadalign_downsample_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 144 | __global__ __vector__ void asc_loadalign_downsample_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 137 | { | 145 | { |
| 138 | asc_init(); | 146 | asc_init(); |
| 139 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 147 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 140 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 148 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 141 | - asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 149 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 142 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 150 | + asc_copy_gm2ub_align(input_local, input, INPUT_STORAGE_ELEMENTS); |
| 143 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 151 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 144 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 152 | + |
| 145 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 153 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 154 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); | ||
| 155 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 146 | asc_vf_call<asc_loadalign_downsample_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); | 156 | asc_vf_call<asc_loadalign_downsample_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 147 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 157 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 148 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 158 | + |
| 159 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 149 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 160 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 161 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 150 | asc_sync(); | 162 | asc_sync(); |
| 151 | } | 163 | } |
| 152 | } // namespace | 164 | } // namespace |
| 153 | 165 | ||
| 154 | int main() | 166 | int main() |
| 155 | { | 167 | { |
| 156 | - std::vector<uint8_t> input(INPUT_ELEMENTS); | 168 | + std::vector<uint8_t> input(INPUT_STORAGE_ELEMENTS, 0); |
| 157 | std::vector<uint8_t> output(OUTPUT_ELEMENTS, 0xff); | 169 | std::vector<uint8_t> output(OUTPUT_ELEMENTS, 0xff); |
| 158 | std::vector<uint8_t> golden(OUTPUT_ELEMENTS, 0); | 170 | std::vector<uint8_t> golden(OUTPUT_ELEMENTS, 0); |
| 159 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); | 171 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); |
| @@ -165,9 +177,9 @@ int main() | |||
| 165 | aclrtSetDevice(0); | 177 | aclrtSetDevice(0); |
| 166 | uint8_t* input_device = nullptr; | 178 | uint8_t* input_device = nullptr; |
| 167 | uint8_t* output_device = nullptr; | 179 | uint8_t* output_device = nullptr; |
| 168 | - aclrtMalloc(reinterpret_cast<void**>(&input_device), INPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 180 | + aclrtMalloc(reinterpret_cast<void**>(&input_device), INPUT_STORAGE_ELEMENTS, ACL_MEM_MALLOC_HUGE_FIRST); |
| 169 | aclrtMalloc(reinterpret_cast<void**>(&output_device), OUTPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 181 | aclrtMalloc(reinterpret_cast<void**>(&output_device), OUTPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); |
| 170 | - aclrtMemcpy(input_device, INPUT_BYTES, input.data(), INPUT_BYTES, ACL_MEMCPY_HOST_TO_DEVICE); | 182 | + aclrtMemcpy(input_device, INPUT_STORAGE_ELEMENTS, input.data(), INPUT_STORAGE_ELEMENTS, ACL_MEMCPY_HOST_TO_DEVICE); |
| 171 | asc_loadalign_downsample_postupdate_kernel<<<1, 0>>>(output_device, input_device); | 183 | asc_loadalign_downsample_postupdate_kernel<<<1, 0>>>(output_device, input_device); |
| 172 | aclrtSynchronizeDevice(); | 184 | aclrtSynchronizeDevice(); |
| 173 | aclrtMemcpy(output.data(), OUTPUT_BYTES, output_device, OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); | 185 | aclrtMemcpy(output.data(), OUTPUT_BYTES, output_device, OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); |
| @@ -79,52 +79,77 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 79 | #include <iostream> | 79 | #include <iostream> |
| 80 | #include <vector> | 80 | #include <vector> |
| 81 | #include "c_api/asc_simd.h" | 81 | #include "c_api/asc_simd.h" |
| 82 | +#include "utils/std/cmath.h" | ||
| 82 | #include "acl/acl.h" | 83 | #include "acl/acl.h" |
| 83 | 84 | ||
| 84 | namespace { | 85 | namespace { |
| 85 | -constexpr uint32_t MASK_BYTES = 32; | 86 | +constexpr uint8_t MUTEX_ID = 0; |
| 86 | 87 | ||
| 88 | + | ||
| 89 | +constexpr uint32_t MASK_WORD_COUNT = 11; | ||
| 90 | +constexpr uint32_t WORDS_PER_MASK = 8; | ||
| 91 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 92 | +constexpr uint32_t REPEAT_COUNT = (MASK_WORD_COUNT + WORDS_PER_MASK - 1) / WORDS_PER_MASK; | ||
| 93 | +constexpr uint32_t STORAGE_WORD_COUNT = REPEAT_COUNT * WORDS_PER_MASK; | ||
| 94 | +constexpr uint32_t TOTAL_MASK_BYTES = STORAGE_WORD_COUNT * sizeof(uint32_t); | ||
| 95 | + | ||
| 96 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 97 | +constexpr uint32_t TOTAL_LENGTH = MASK_WORD_COUNT; | ||
| 98 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint32_t); | ||
| 87 | __simd_vf__ inline void asc_loadalign_mask_vf( | 99 | __simd_vf__ inline void asc_loadalign_mask_vf( |
| 88 | - __ubuf__ uint32_t* output, __ubuf__ uint32_t* mask_input) | 100 | + __ubuf__ uint32_t* output, __ubuf__ uint32_t* mask_input, uint32_t one_repeat_size, uint16_t repeat_time) |
| 89 | { | 101 | { |
| 90 | - vector_bool mask = asc_loadalign_mask(mask_input); | 102 | + uint32_t remaining = MASK_WORD_COUNT; |
| 91 | - asc_storealign(output, mask); | 103 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 104 | + const uint32_t valid_count = remaining > WORDS_PER_MASK ? WORDS_PER_MASK : remaining; | ||
| 105 | + const uint32_t offset = i * WORDS_PER_MASK; | ||
| 106 | + vector_bool mask = asc_loadalign_mask(mask_input + offset); | ||
| 107 | + asc_storealign(output + offset, mask); | ||
| 108 | + remaining -= valid_count; | ||
| 109 | + } | ||
| 92 | } | 110 | } |
| 93 | 111 | ||
| 94 | __global__ __vector__ void asc_loadalign_mask_kernel( | 112 | __global__ __vector__ void asc_loadalign_mask_kernel( |
| 95 | __gm__ uint32_t* output, __gm__ uint32_t* mask_input) | 113 | __gm__ uint32_t* output, __gm__ uint32_t* mask_input) |
| 96 | { | 114 | { |
| 97 | asc_init(); | 115 | asc_init(); |
| 98 | - __ubuf__ uint32_t output_local[MASK_BYTES / sizeof(uint32_t)]; | 116 | + __ubuf__ uint32_t output_local[STORAGE_WORD_COUNT]; |
| 99 | - __ubuf__ uint32_t mask_local[MASK_BYTES / sizeof(uint32_t)]; | 117 | + __ubuf__ uint32_t mask_local[STORAGE_WORD_COUNT]; |
| 100 | - asc_copy_gm2ub_align(mask_local, mask_input, MASK_BYTES); | 118 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 101 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 119 | + asc_copy_gm2ub_align(mask_local, mask_input, TOTAL_MASK_BYTES); |
| 102 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 120 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 103 | - asc_vf_call<asc_loadalign_mask_vf>(output_local, mask_local); | 121 | + |
| 104 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 122 | + uint32_t one_repeat_size = asc_get_vf_len() / sizeof(uint32_t) / 8; |
| 105 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 123 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 106 | - asc_copy_ub2gm_align(output, output_local, MASK_BYTES); | 124 | + asc_lock(PIPE_V, MUTEX_ID); |
| 125 | + asc_vf_call<asc_loadalign_mask_vf>(output_local, mask_local, one_repeat_size, repeat_time); | ||
| 126 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 127 | + | ||
| 128 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 129 | + asc_copy_ub2gm_align(output, output_local, TOTAL_MASK_BYTES); | ||
| 130 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 107 | asc_sync(); | 131 | asc_sync(); |
| 108 | } | 132 | } |
| 109 | } // namespace | 133 | } // namespace |
| 110 | 134 | ||
| 111 | int main() | 135 | int main() |
| 112 | { | 136 | { |
| 113 | - std::vector<uint32_t> output(MASK_BYTES / sizeof(uint32_t), 0); | 137 | + std::vector<uint32_t> output(STORAGE_WORD_COUNT, 0); |
| 114 | - std::vector<uint32_t> mask_input(MASK_BYTES / sizeof(uint32_t), 0x55555555u); | 138 | + std::vector<uint32_t> mask_input(STORAGE_WORD_COUNT, 0x55555555u); |
| 115 | 139 | ||
| 116 | aclInit(nullptr); | 140 | aclInit(nullptr); |
| 117 | aclrtSetDevice(0); | 141 | aclrtSetDevice(0); |
| 118 | uint32_t* output_device = nullptr; | 142 | uint32_t* output_device = nullptr; |
| 119 | uint32_t* mask_device = nullptr; | 143 | uint32_t* mask_device = nullptr; |
| 120 | - aclrtMalloc(reinterpret_cast<void**>(&output_device), MASK_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 144 | + aclrtMalloc(reinterpret_cast<void**>(&output_device), TOTAL_MASK_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); |
| 121 | - aclrtMalloc(reinterpret_cast<void**>(&mask_device), MASK_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 145 | + aclrtMalloc(reinterpret_cast<void**>(&mask_device), TOTAL_MASK_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); |
| 122 | - aclrtMemcpy(mask_device, MASK_BYTES, mask_input.data(), MASK_BYTES, ACL_MEMCPY_HOST_TO_DEVICE); | 146 | + aclrtMemcpy(mask_device, TOTAL_MASK_BYTES, mask_input.data(), TOTAL_MASK_BYTES, ACL_MEMCPY_HOST_TO_DEVICE); |
| 123 | asc_loadalign_mask_kernel<<<1, 0>>>(output_device, mask_device); | 147 | asc_loadalign_mask_kernel<<<1, 0>>>(output_device, mask_device); |
| 124 | aclrtSynchronizeDevice(); | 148 | aclrtSynchronizeDevice(); |
| 125 | - aclrtMemcpy(output.data(), MASK_BYTES, output_device, MASK_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); | 149 | + aclrtMemcpy(output.data(), TOTAL_MASK_BYTES, output_device, TOTAL_MASK_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); |
| 126 | 150 | ||
| 127 | - const bool passed = output == mask_input; | 151 | + bool passed = true; |
| 152 | + for (uint32_t i = 0; i < MASK_WORD_COUNT; ++i) passed = passed && output[i] == mask_input[i]; | ||
| 128 | std::cout << (passed ? "[Success]" : "[Failed]") << " asc_loadalign_mask example." << std::endl; | 153 | std::cout << (passed ? "[Success]" : "[Failed]") << " asc_loadalign_mask example." << std::endl; |
| 129 | aclrtFree(output_device); | 154 | aclrtFree(output_device); |
| 130 | aclrtFree(mask_device); | 155 | aclrtFree(mask_device); |
| @@ -79,54 +79,85 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 79 | #include <iostream> | 79 | #include <iostream> |
| 80 | #include <vector> | 80 | #include <vector> |
| 81 | #include "c_api/asc_simd.h" | 81 | #include "c_api/asc_simd.h" |
| 82 | +#include "utils/std/cmath.h" | ||
| 82 | #include "acl/acl.h" | 83 | #include "acl/acl.h" |
| 83 | 84 | ||
| 84 | namespace { | 85 | namespace { |
| 85 | -constexpr uint32_t MASK_INPUT_BYTES = 64; | 86 | +constexpr uint8_t MUTEX_ID = 0; |
| 86 | -constexpr uint32_t MASK_OUTPUT_BYTES = 32; | ||
| 87 | 87 | ||
| 88 | + | ||
| 89 | +constexpr uint32_t MASK_OUTPUT_WORD_COUNT = 11; | ||
| 90 | +constexpr uint32_t OUTPUT_WORDS_PER_MASK = 8; | ||
| 91 | +constexpr uint32_t INPUT_WORDS_PER_MASK = 16; | ||
| 92 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 93 | +constexpr uint32_t REPEAT_COUNT = | ||
| 94 | + (MASK_OUTPUT_WORD_COUNT + OUTPUT_WORDS_PER_MASK - 1) / OUTPUT_WORDS_PER_MASK; | ||
| 95 | +constexpr uint32_t MASK_INPUT_WORD_COUNT = REPEAT_COUNT * INPUT_WORDS_PER_MASK; | ||
| 96 | +constexpr uint32_t MASK_OUTPUT_STORAGE_WORD_COUNT = REPEAT_COUNT * OUTPUT_WORDS_PER_MASK; | ||
| 97 | +constexpr uint32_t TOTAL_MASK_INPUT_BYTES = MASK_INPUT_WORD_COUNT * sizeof(uint32_t); | ||
| 98 | +constexpr uint32_t TOTAL_MASK_OUTPUT_BYTES = MASK_OUTPUT_STORAGE_WORD_COUNT * sizeof(uint32_t); | ||
| 99 | + | ||
| 100 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 101 | +constexpr uint32_t TOTAL_LENGTH = MASK_OUTPUT_WORD_COUNT; | ||
| 102 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint32_t); | ||
| 88 | __simd_vf__ inline void asc_loadalign_mask_downsample_vf( | 103 | __simd_vf__ inline void asc_loadalign_mask_downsample_vf( |
| 89 | - __ubuf__ uint32_t* output, __ubuf__ uint32_t* mask_input) | 104 | + __ubuf__ uint32_t* output, __ubuf__ uint32_t* mask_input, uint32_t one_repeat_size, uint16_t repeat_time) |
| 90 | { | 105 | { |
| 91 | - vector_bool mask = asc_loadalign_mask_downsample(mask_input); | 106 | + uint32_t remaining = MASK_OUTPUT_WORD_COUNT; |
| 92 | - asc_storealign(output, mask); | 107 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 108 | + const uint32_t valid_count = remaining > OUTPUT_WORDS_PER_MASK ? OUTPUT_WORDS_PER_MASK : remaining; | ||
| 109 | + const uint32_t input_offset = i * INPUT_WORDS_PER_MASK; | ||
| 110 | + const uint32_t output_offset = i * OUTPUT_WORDS_PER_MASK; | ||
| 111 | + vector_bool mask = asc_loadalign_mask_downsample(mask_input + input_offset); | ||
| 112 | + asc_storealign(output + output_offset, mask); | ||
| 113 | + remaining -= valid_count; | ||
| 114 | + } | ||
| 93 | } | 115 | } |
| 94 | 116 | ||
| 95 | __global__ __vector__ void asc_loadalign_mask_downsample_kernel( | 117 | __global__ __vector__ void asc_loadalign_mask_downsample_kernel( |
| 96 | __gm__ uint32_t* output, __gm__ uint32_t* mask_input) | 118 | __gm__ uint32_t* output, __gm__ uint32_t* mask_input) |
| 97 | { | 119 | { |
| 98 | asc_init(); | 120 | asc_init(); |
| 99 | - __ubuf__ uint32_t output_local[MASK_OUTPUT_BYTES / sizeof(uint32_t)]; | 121 | + __ubuf__ uint32_t output_local[MASK_OUTPUT_STORAGE_WORD_COUNT]; |
| 100 | - __ubuf__ uint32_t mask_local[MASK_INPUT_BYTES / sizeof(uint32_t)]; | 122 | + __ubuf__ uint32_t mask_local[MASK_INPUT_WORD_COUNT]; |
| 101 | - asc_copy_gm2ub_align(mask_local, mask_input, MASK_INPUT_BYTES); | 123 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 102 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 124 | + asc_copy_gm2ub_align(mask_local, mask_input, TOTAL_MASK_INPUT_BYTES); |
| 103 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 125 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 104 | - asc_vf_call<asc_loadalign_mask_downsample_vf>(output_local, mask_local); | 126 | + |
| 105 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 127 | + uint32_t one_repeat_size = asc_get_vf_len() / sizeof(uint32_t) / 8; |
| 106 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 128 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 107 | - asc_copy_ub2gm_align(output, output_local, MASK_OUTPUT_BYTES); | 129 | + asc_lock(PIPE_V, MUTEX_ID); |
| 130 | + asc_vf_call<asc_loadalign_mask_downsample_vf>(output_local, mask_local, one_repeat_size, repeat_time); | ||
| 131 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 132 | + | ||
| 133 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 134 | + asc_copy_ub2gm_align(output, output_local, TOTAL_MASK_OUTPUT_BYTES); | ||
| 135 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 108 | asc_sync(); | 136 | asc_sync(); |
| 109 | } | 137 | } |
| 110 | } // namespace | 138 | } // namespace |
| 111 | 139 | ||
| 112 | int main() | 140 | int main() |
| 113 | { | 141 | { |
| 114 | - std::vector<uint32_t> output(MASK_OUTPUT_BYTES / sizeof(uint32_t), 0); | 142 | + std::vector<uint32_t> output(MASK_OUTPUT_STORAGE_WORD_COUNT, 0); |
| 115 | - std::vector<uint32_t> golden(MASK_OUTPUT_BYTES / sizeof(uint32_t), 0x55555555u); | 143 | + std::vector<uint32_t> golden(MASK_OUTPUT_STORAGE_WORD_COUNT, 0x55555555u); |
| 116 | - std::vector<uint32_t> mask_input(MASK_INPUT_BYTES / sizeof(uint32_t), 0x33333333u); | 144 | + std::vector<uint32_t> mask_input(MASK_INPUT_WORD_COUNT, 0x33333333u); |
| 117 | 145 | ||
| 118 | aclInit(nullptr); | 146 | aclInit(nullptr); |
| 119 | aclrtSetDevice(0); | 147 | aclrtSetDevice(0); |
| 120 | uint32_t* output_device = nullptr; | 148 | uint32_t* output_device = nullptr; |
| 121 | uint32_t* mask_device = nullptr; | 149 | uint32_t* mask_device = nullptr; |
| 122 | - aclrtMalloc(reinterpret_cast<void**>(&output_device), MASK_OUTPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 150 | + aclrtMalloc(reinterpret_cast<void**>(&output_device), TOTAL_MASK_OUTPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); |
| 123 | - aclrtMalloc(reinterpret_cast<void**>(&mask_device), MASK_INPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 151 | + aclrtMalloc(reinterpret_cast<void**>(&mask_device), TOTAL_MASK_INPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); |
| 124 | - aclrtMemcpy(mask_device, MASK_INPUT_BYTES, mask_input.data(), MASK_INPUT_BYTES, ACL_MEMCPY_HOST_TO_DEVICE); | 152 | + aclrtMemcpy(mask_device, TOTAL_MASK_INPUT_BYTES, mask_input.data(), TOTAL_MASK_INPUT_BYTES, |
| 153 | + ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 125 | asc_loadalign_mask_downsample_kernel<<<1, 0>>>(output_device, mask_device); | 154 | asc_loadalign_mask_downsample_kernel<<<1, 0>>>(output_device, mask_device); |
| 126 | aclrtSynchronizeDevice(); | 155 | aclrtSynchronizeDevice(); |
| 127 | - aclrtMemcpy(output.data(), MASK_OUTPUT_BYTES, output_device, MASK_OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); | 156 | + aclrtMemcpy(output.data(), TOTAL_MASK_OUTPUT_BYTES, output_device, TOTAL_MASK_OUTPUT_BYTES, |
| 157 | + ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 128 | 158 | ||
| 129 | - const bool passed = output == golden; | 159 | + bool passed = true; |
| 160 | + for (uint32_t i = 0; i < MASK_OUTPUT_WORD_COUNT; ++i) passed = passed && output[i] == golden[i]; | ||
| 130 | std::cout << (passed ? "[Success]" : "[Failed]") | 161 | std::cout << (passed ? "[Success]" : "[Failed]") |
| 131 | << " asc_loadalign_mask_downsample example." << std::endl; | 162 | << " asc_loadalign_mask_downsample example." << std::endl; |
| 132 | aclrtFree(output_device); | 163 | aclrtFree(output_device); |
| @@ -79,58 +79,93 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 79 | #include <iostream> | 79 | #include <iostream> |
| 80 | #include <vector> | 80 | #include <vector> |
| 81 | #include "c_api/asc_simd.h" | 81 | #include "c_api/asc_simd.h" |
| 82 | +#include "utils/std/cmath.h" | ||
| 82 | #include "acl/acl.h" | 83 | #include "acl/acl.h" |
| 83 | 84 | ||
| 84 | namespace { | 85 | namespace { |
| 85 | -constexpr uint32_t MASK_DATA_BYTES = 16; | 86 | +constexpr uint8_t MUTEX_ID = 0; |
| 86 | -constexpr uint32_t MASK_STORAGE_BYTES = 32; | ||
| 87 | -constexpr uint32_t MASK_OUTPUT_BYTES = 32; | ||
| 88 | 87 | ||
| 88 | + | ||
| 89 | +constexpr uint32_t MASK_OUTPUT_WORD_COUNT = 11; | ||
| 90 | +constexpr uint32_t MASK_DATA_WORDS_PER_REPEAT = 4; | ||
| 91 | +constexpr uint32_t MASK_STORAGE_WORDS_PER_REPEAT = 8; | ||
| 92 | +constexpr uint32_t MASK_OUTPUT_WORDS_PER_REPEAT = 8; | ||
| 93 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 94 | +constexpr uint32_t REPEAT_COUNT = | ||
| 95 | + (MASK_OUTPUT_WORD_COUNT + MASK_OUTPUT_WORDS_PER_REPEAT - 1) / MASK_OUTPUT_WORDS_PER_REPEAT; | ||
| 96 | +constexpr uint32_t MASK_STORAGE_WORD_COUNT = MASK_STORAGE_WORDS_PER_REPEAT * REPEAT_COUNT; | ||
| 97 | +constexpr uint32_t MASK_OUTPUT_STORAGE_WORD_COUNT = MASK_OUTPUT_WORDS_PER_REPEAT * REPEAT_COUNT; | ||
| 98 | +constexpr uint32_t TOTAL_MASK_STORAGE_BYTES = MASK_STORAGE_WORD_COUNT * sizeof(uint32_t); | ||
| 99 | +constexpr uint32_t TOTAL_MASK_OUTPUT_BYTES = MASK_OUTPUT_STORAGE_WORD_COUNT * sizeof(uint32_t); | ||
| 100 | + | ||
| 101 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 102 | +constexpr uint32_t TOTAL_LENGTH = MASK_OUTPUT_WORD_COUNT; | ||
| 103 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint32_t); | ||
| 89 | __simd_vf__ inline void asc_loadalign_mask_upsample_vf( | 104 | __simd_vf__ inline void asc_loadalign_mask_upsample_vf( |
| 90 | - __ubuf__ uint32_t* output, __ubuf__ uint32_t* mask_input) | 105 | + __ubuf__ uint32_t* output, __ubuf__ uint32_t* mask_input, uint32_t one_repeat_size, uint16_t repeat_time) |
| 91 | { | 106 | { |
| 92 | - vector_bool mask = asc_loadalign_mask_upsample(mask_input); | 107 | + uint32_t remaining = MASK_OUTPUT_WORD_COUNT; |
| 93 | - asc_storealign(output, mask); | 108 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 109 | + const uint32_t valid_count = remaining > MASK_OUTPUT_WORDS_PER_REPEAT ? | ||
| 110 | + MASK_OUTPUT_WORDS_PER_REPEAT : remaining; | ||
| 111 | + const uint32_t input_offset = i * MASK_STORAGE_WORDS_PER_REPEAT; | ||
| 112 | + const uint32_t output_offset = i * MASK_OUTPUT_WORDS_PER_REPEAT; | ||
| 113 | + vector_bool mask = asc_loadalign_mask_upsample(mask_input + input_offset); | ||
| 114 | + asc_storealign(output + output_offset, mask); | ||
| 115 | + remaining -= valid_count; | ||
| 116 | + } | ||
| 94 | } | 117 | } |
| 95 | 118 | ||
| 96 | __global__ __vector__ void asc_loadalign_mask_upsample_kernel( | 119 | __global__ __vector__ void asc_loadalign_mask_upsample_kernel( |
| 97 | __gm__ uint32_t* output, __gm__ uint32_t* mask_input) | 120 | __gm__ uint32_t* output, __gm__ uint32_t* mask_input) |
| 98 | { | 121 | { |
| 99 | asc_init(); | 122 | asc_init(); |
| 100 | - __ubuf__ uint32_t output_local[MASK_OUTPUT_BYTES / sizeof(uint32_t)]; | 123 | + __ubuf__ uint32_t output_local[MASK_OUTPUT_STORAGE_WORD_COUNT]; |
| 101 | - __ubuf__ uint32_t mask_local[MASK_STORAGE_BYTES / sizeof(uint32_t)]; | 124 | + __ubuf__ uint32_t mask_local[MASK_STORAGE_WORD_COUNT]; |
| 102 | - asc_copy_gm2ub_align(mask_local, mask_input, MASK_DATA_BYTES); | 125 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 103 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 126 | + asc_copy_gm2ub_align(mask_local, mask_input, TOTAL_MASK_STORAGE_BYTES); |
| 104 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 127 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 105 | - asc_vf_call<asc_loadalign_mask_upsample_vf>(output_local, mask_local); | 128 | + |
| 106 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 129 | + uint32_t one_repeat_size = asc_get_vf_len() / sizeof(uint32_t) / 8; |
| 107 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 130 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 108 | - asc_copy_ub2gm_align(output, output_local, MASK_OUTPUT_BYTES); | 131 | + asc_lock(PIPE_V, MUTEX_ID); |
| 132 | + asc_vf_call<asc_loadalign_mask_upsample_vf>(output_local, mask_local, one_repeat_size, repeat_time); | ||
| 133 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 134 | + | ||
| 135 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 136 | + asc_copy_ub2gm_align(output, output_local, TOTAL_MASK_OUTPUT_BYTES); | ||
| 137 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 109 | asc_sync(); | 138 | asc_sync(); |
| 110 | } | 139 | } |
| 111 | } // namespace | 140 | } // namespace |
| 112 | 141 | ||
| 113 | int main() | 142 | int main() |
| 114 | { | 143 | { |
| 115 | - std::vector<uint32_t> output(MASK_OUTPUT_BYTES / sizeof(uint32_t), 0); | 144 | + std::vector<uint32_t> output(MASK_OUTPUT_STORAGE_WORD_COUNT, 0); |
| 116 | - std::vector<uint32_t> golden(MASK_OUTPUT_BYTES / sizeof(uint32_t), 0x33333333u); | 145 | + std::vector<uint32_t> golden(MASK_OUTPUT_STORAGE_WORD_COUNT, 0x33333333u); |
| 117 | - std::vector<uint32_t> mask_input(MASK_STORAGE_BYTES / sizeof(uint32_t), 0); | 146 | + std::vector<uint32_t> mask_input(MASK_STORAGE_WORD_COUNT, 0); |
| 118 | - for (uint32_t i = 0; i < MASK_DATA_BYTES / sizeof(uint32_t); ++i) { | 147 | + for (uint32_t repeat = 0; repeat < REPEAT_COUNT; ++repeat) { |
| 119 | - mask_input[i] = 0x55555555u; | 148 | + const uint32_t offset = repeat * MASK_STORAGE_WORDS_PER_REPEAT; |
| 149 | + for (uint32_t i = 0; i < MASK_DATA_WORDS_PER_REPEAT; ++i) { | ||
| 150 | + mask_input[offset + i] = 0x55555555u; | ||
| 151 | + } | ||
| 120 | } | 152 | } |
| 121 | 153 | ||
| 122 | aclInit(nullptr); | 154 | aclInit(nullptr); |
| 123 | aclrtSetDevice(0); | 155 | aclrtSetDevice(0); |
| 124 | uint32_t* output_device = nullptr; | 156 | uint32_t* output_device = nullptr; |
| 125 | uint32_t* mask_device = nullptr; | 157 | uint32_t* mask_device = nullptr; |
| 126 | - aclrtMalloc(reinterpret_cast<void**>(&output_device), MASK_OUTPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 158 | + aclrtMalloc(reinterpret_cast<void**>(&output_device), TOTAL_MASK_OUTPUT_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); |
| 127 | - aclrtMalloc(reinterpret_cast<void**>(&mask_device), MASK_STORAGE_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); | 159 | + aclrtMalloc(reinterpret_cast<void**>(&mask_device), TOTAL_MASK_STORAGE_BYTES, ACL_MEM_MALLOC_HUGE_FIRST); |
| 128 | - aclrtMemcpy(mask_device, MASK_STORAGE_BYTES, mask_input.data(), MASK_STORAGE_BYTES, ACL_MEMCPY_HOST_TO_DEVICE); | 160 | + aclrtMemcpy(mask_device, TOTAL_MASK_STORAGE_BYTES, mask_input.data(), TOTAL_MASK_STORAGE_BYTES, |
| 161 | + ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 129 | asc_loadalign_mask_upsample_kernel<<<1, 0>>>(output_device, mask_device); | 162 | asc_loadalign_mask_upsample_kernel<<<1, 0>>>(output_device, mask_device); |
| 130 | aclrtSynchronizeDevice(); | 163 | aclrtSynchronizeDevice(); |
| 131 | - aclrtMemcpy(output.data(), MASK_OUTPUT_BYTES, output_device, MASK_OUTPUT_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); | 164 | + aclrtMemcpy(output.data(), TOTAL_MASK_OUTPUT_BYTES, output_device, TOTAL_MASK_OUTPUT_BYTES, |
| 165 | + ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 132 | 166 | ||
| 133 | - const bool passed = output == golden; | 167 | + bool passed = true; |
| 168 | + for (uint32_t i = 0; i < MASK_OUTPUT_WORD_COUNT; ++i) passed = passed && output[i] == golden[i]; | ||
| 134 | std::cout << (passed ? "[Success]" : "[Failed]") | 169 | std::cout << (passed ? "[Success]" : "[Failed]") |
| 135 | << " asc_loadalign_mask_upsample example." << std::endl; | 170 | << " asc_loadalign_mask_upsample example." << std::endl; |
| 136 | aclrtFree(output_device); | 171 | aclrtFree(output_device); |
| @@ -169,12 +169,10 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 169 | #include <iostream> | 169 | #include <iostream> |
| 170 | #include <vector> | 170 | #include <vector> |
| 171 | #include "c_api/asc_simd.h" | 171 | #include "c_api/asc_simd.h" |
| 172 | +#include "utils/std/cmath.h" | ||
| 172 | #include "acl/acl.h" | 173 | #include "acl/acl.h" |
| 173 | namespace { | 174 | namespace { |
| 174 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 175 | +constexpr uint8_t MUTEX_ID = 0; |
| 175 | -{ | ||
| 176 | - return (numerator + denominator - 1) / denominator; | ||
| 177 | -} | ||
| 178 | 176 | ||
| 179 | template <typename T> | 177 | template <typename T> |
| 180 | void print_data(const char* label, const std::vector<T>& dst_regs) | 178 | void print_data(const char* label, const std::vector<T>& dst_regs) |
| @@ -186,14 +184,22 @@ void print_data(const char* label, const std::vector<T>& dst_regs) | |||
| 186 | std::cout << std::endl; | 184 | std::cout << std::endl; |
| 187 | } | 185 | } |
| 188 | 186 | ||
| 189 | -constexpr uint32_t BUFFER_ELEMENTS = 512; | 187 | +constexpr uint32_t BUFFER_ELEMENTS = 260; |
| 188 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 189 | +constexpr uint32_t BUFFER_STORAGE_ELEMENTS = | ||
| 190 | + AscendC::Std::ceil_div(BUFFER_ELEMENTS, ELEMENTS_PER_REGISTER) * ELEMENTS_PER_REGISTER; | ||
| 190 | constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t); | 191 | constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t); |
| 192 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 193 | +constexpr uint32_t TOTAL_LENGTH = BUFFER_ELEMENTS; | ||
| 194 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 191 | __simd_vf__ inline void asc_loadalign_postupdate_vf(__ubuf__ uint8_t* output, | 195 | __simd_vf__ inline void asc_loadalign_postupdate_vf(__ubuf__ uint8_t* output, |
| 192 | __ubuf__ uint8_t* input, | 196 | __ubuf__ uint8_t* input, |
| 193 | - uint16_t one_repeat_size, uint16_t repeat_time) | 197 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 194 | { | 198 | { |
| 195 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 199 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 200 | + uint32_t remaining_length = BUFFER_ELEMENTS; | ||
| 196 | for (uint16_t i = 0; i < repeat_time; ++i) { | 201 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 202 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 197 | vector_uint8_t src_reg; | 203 | vector_uint8_t src_reg; |
| 198 | asc_loadalign_postupdate(src_reg, input, one_repeat_size); | 204 | asc_loadalign_postupdate(src_reg, input, one_repeat_size); |
| 199 | asc_storealign(output + i * one_repeat_size, src_reg, mask); | 205 | asc_storealign(output + i * one_repeat_size, src_reg, mask); |
| @@ -203,20 +209,24 @@ __simd_vf__ inline void asc_loadalign_postupdate_vf(__ubuf__ uint8_t* output, | |||
| 203 | __global__ __vector__ void asc_loadalign_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 209 | __global__ __vector__ void asc_loadalign_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 204 | { | 210 | { |
| 205 | asc_init(); | 211 | asc_init(); |
| 206 | - __ubuf__ uint8_t output_local[BUFFER_ELEMENTS], input_local[BUFFER_ELEMENTS]; | 212 | + __ubuf__ uint8_t output_local[BUFFER_STORAGE_ELEMENTS], input_local[BUFFER_STORAGE_ELEMENTS]; |
| 213 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 207 | asc_copy_gm2ub_align(input_local, input, BUFFER_BYTES); | 214 | asc_copy_gm2ub_align(input_local, input, BUFFER_BYTES); |
| 208 | 215 | ||
| 209 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 216 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 210 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | ||
| 211 | 217 | ||
| 212 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 218 | + |
| 213 | - uint16_t repeat_time = ceil_division(BUFFER_ELEMENTS, one_repeat_size); | 219 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 220 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); | ||
| 221 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 214 | asc_vf_call<asc_loadalign_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); | 222 | asc_vf_call<asc_loadalign_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 215 | 223 | ||
| 216 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 224 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 217 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 225 | + |
| 226 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 218 | 227 | ||
| 219 | asc_copy_ub2gm_align(output, output_local, BUFFER_BYTES); | 228 | asc_copy_ub2gm_align(output, output_local, BUFFER_BYTES); |
| 229 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 220 | asc_sync(); | 230 | asc_sync(); |
| 221 | } | 231 | } |
| 222 | } // namespace | 232 | } // namespace |
| @@ -176,25 +176,33 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 176 | #include <iostream> | 176 | #include <iostream> |
| 177 | #include <vector> | 177 | #include <vector> |
| 178 | #include "c_api/asc_simd.h" | 178 | #include "c_api/asc_simd.h" |
| 179 | +#include "utils/std/cmath.h" | ||
| 179 | #include "acl/acl.h" | 180 | #include "acl/acl.h" |
| 180 | 181 | ||
| 181 | namespace { | 182 | namespace { |
| 182 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 183 | +constexpr uint8_t MUTEX_ID = 0; |
| 183 | -{ | ||
| 184 | - return (numerator + denominator - 1) / denominator; | ||
| 185 | -} | ||
| 186 | 184 | ||
| 187 | -constexpr uint32_t INPUT_ELEMENTS = 256; | 185 | +constexpr uint32_t INPUT_ELEMENTS = 260; |
| 188 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 186 | +constexpr uint32_t OUTPUT_ELEMENTS = 520; |
| 189 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 187 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); |
| 190 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 188 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 189 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 190 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 191 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 192 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 193 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 128; | ||
| 191 | 194 | ||
| 195 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 196 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 197 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 192 | __simd_vf__ inline void asc_loadalign_unpack_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, | 198 | __simd_vf__ inline void asc_loadalign_unpack_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, |
| 193 | - uint16_t one_repeat_size, uint16_t repeat_time) | 199 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 194 | { | 200 | { |
| 195 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 201 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 202 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 196 | vector_uint8_t dst_reg; | 203 | vector_uint8_t dst_reg; |
| 197 | for (uint16_t i = 0; i < repeat_time; ++i) { | 204 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 205 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 198 | asc_loadalign_unpack(dst_reg, input + i * 128); | 206 | asc_loadalign_unpack(dst_reg, input + i * 128); |
| 199 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 207 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 200 | } | 208 | } |
| @@ -203,17 +211,21 @@ __simd_vf__ inline void asc_loadalign_unpack_vf(__ubuf__ uint8_t* output, __ubuf | |||
| 203 | __global__ __vector__ void asc_loadalign_unpack_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 211 | __global__ __vector__ void asc_loadalign_unpack_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 204 | { | 212 | { |
| 205 | asc_init(); | 213 | asc_init(); |
| 206 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 214 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 207 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 215 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 216 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 208 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 217 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 209 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 218 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 210 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 219 | + |
| 211 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 220 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 212 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 221 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 222 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 213 | asc_vf_call<asc_loadalign_unpack_vf>(output_local, input_local, one_repeat_size, repeat_time); | 223 | asc_vf_call<asc_loadalign_unpack_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 214 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 224 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 215 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 225 | + |
| 226 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 216 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 227 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 228 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 217 | asc_sync(); | 229 | asc_sync(); |
| 218 | } | 230 | } |
| 219 | } // namespace | 231 | } // namespace |
| @@ -172,25 +172,33 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 172 | #include <iostream> | 172 | #include <iostream> |
| 173 | #include <vector> | 173 | #include <vector> |
| 174 | #include "c_api/asc_simd.h" | 174 | #include "c_api/asc_simd.h" |
| 175 | +#include "utils/std/cmath.h" | ||
| 175 | #include "acl/acl.h" | 176 | #include "acl/acl.h" |
| 176 | 177 | ||
| 177 | namespace { | 178 | namespace { |
| 178 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 179 | +constexpr uint8_t MUTEX_ID = 0; |
| 179 | -{ | ||
| 180 | - return (numerator + denominator - 1) / denominator; | ||
| 181 | -} | ||
| 182 | 180 | ||
| 183 | -constexpr uint32_t INPUT_ELEMENTS = 128; | 181 | +constexpr uint32_t INPUT_ELEMENTS = 133; |
| 184 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 182 | +constexpr uint32_t OUTPUT_ELEMENTS = INPUT_ELEMENTS * 4; |
| 185 | -constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | ||
| 186 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 183 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 184 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 185 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 186 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 187 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 188 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 64; | ||
| 189 | +constexpr uint32_t INPUT_BYTES = INPUT_STORAGE_ELEMENTS * sizeof(uint8_t); | ||
| 187 | 190 | ||
| 191 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 192 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 193 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 188 | __simd_vf__ inline void asc_loadalign_unpack4_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, | 194 | __simd_vf__ inline void asc_loadalign_unpack4_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, |
| 189 | - uint16_t one_repeat_size, uint16_t repeat_time) | 195 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 190 | { | 196 | { |
| 191 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 197 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 198 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 192 | vector_uint8_t dst_reg; | 199 | vector_uint8_t dst_reg; |
| 193 | for (uint16_t i = 0; i < repeat_time; ++i) { | 200 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 201 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 194 | asc_loadalign_unpack4(dst_reg, input + i * 64); | 202 | asc_loadalign_unpack4(dst_reg, input + i * 64); |
| 195 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 203 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 196 | } | 204 | } |
| @@ -199,24 +207,28 @@ __simd_vf__ inline void asc_loadalign_unpack4_vf(__ubuf__ uint8_t* output, __ubu | |||
| 199 | __global__ __vector__ void asc_loadalign_unpack4_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 207 | __global__ __vector__ void asc_loadalign_unpack4_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 200 | { | 208 | { |
| 201 | asc_init(); | 209 | asc_init(); |
| 202 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 210 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 203 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 211 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 212 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 204 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 213 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 205 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 214 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 206 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 215 | + |
| 207 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 216 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 208 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 217 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 218 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 209 | asc_vf_call<asc_loadalign_unpack4_vf>(output_local, input_local, one_repeat_size, repeat_time); | 219 | asc_vf_call<asc_loadalign_unpack4_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 210 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 220 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 211 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 221 | + |
| 222 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 212 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 223 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 224 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 213 | asc_sync(); | 225 | asc_sync(); |
| 214 | } | 226 | } |
| 215 | } // namespace | 227 | } // namespace |
| 216 | 228 | ||
| 217 | int main() | 229 | int main() |
| 218 | { | 230 | { |
| 219 | - std::vector<uint8_t> input(INPUT_ELEMENTS); | 231 | + std::vector<uint8_t> input(INPUT_STORAGE_ELEMENTS, 0); |
| 220 | std::vector<uint8_t> output(OUTPUT_ELEMENTS, 0xff); | 232 | std::vector<uint8_t> output(OUTPUT_ELEMENTS, 0xff); |
| 221 | std::vector<uint8_t> golden(OUTPUT_ELEMENTS, 0); | 233 | std::vector<uint8_t> golden(OUTPUT_ELEMENTS, 0); |
| 222 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); | 234 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); |
| @@ -95,27 +95,35 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 95 | #include <iostream> | 95 | #include <iostream> |
| 96 | #include <vector> | 96 | #include <vector> |
| 97 | #include "c_api/asc_simd.h" | 97 | #include "c_api/asc_simd.h" |
| 98 | +#include "utils/std/cmath.h" | ||
| 98 | #include "acl/acl.h" | 99 | #include "acl/acl.h" |
| 99 | 100 | ||
| 100 | namespace { | 101 | namespace { |
| 101 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 102 | +constexpr uint8_t MUTEX_ID = 0; |
| 102 | -{ | ||
| 103 | - return (numerator + denominator - 1) / denominator; | ||
| 104 | -} | ||
| 105 | 103 | ||
| 106 | -constexpr uint32_t INPUT_ELEMENTS = 128; | 104 | +constexpr uint32_t INPUT_ELEMENTS = 133; |
| 107 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 105 | +constexpr uint32_t OUTPUT_ELEMENTS = INPUT_ELEMENTS * 4; |
| 108 | -constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | ||
| 109 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 106 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 107 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 108 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 109 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 110 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 111 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 64; | ||
| 112 | +constexpr uint32_t INPUT_BYTES = INPUT_STORAGE_ELEMENTS * sizeof(uint8_t); | ||
| 110 | 113 | ||
| 114 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 115 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 116 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 111 | __simd_vf__ inline void asc_loadalign_unpack4_postupdate_vf(__ubuf__ uint8_t* output, | 117 | __simd_vf__ inline void asc_loadalign_unpack4_postupdate_vf(__ubuf__ uint8_t* output, |
| 112 | __ubuf__ uint8_t* input, | 118 | __ubuf__ uint8_t* input, |
| 113 | - uint16_t one_repeat_size, uint16_t repeat_time) | 119 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 114 | { | 120 | { |
| 115 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 121 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 122 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 116 | vector_uint8_t dst_reg; | 123 | vector_uint8_t dst_reg; |
| 117 | __ubuf__ uint8_t* src = input; | 124 | __ubuf__ uint8_t* src = input; |
| 118 | for (uint16_t i = 0; i < repeat_time; ++i) { | 125 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 126 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 119 | asc_loadalign_unpack4_postupdate(dst_reg, src, 64); | 127 | asc_loadalign_unpack4_postupdate(dst_reg, src, 64); |
| 120 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 128 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 121 | } | 129 | } |
| @@ -124,24 +132,28 @@ __simd_vf__ inline void asc_loadalign_unpack4_postupdate_vf(__ubuf__ uint8_t* ou | |||
| 124 | __global__ __vector__ void asc_loadalign_unpack4_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 132 | __global__ __vector__ void asc_loadalign_unpack4_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 125 | { | 133 | { |
| 126 | asc_init(); | 134 | asc_init(); |
| 127 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 135 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 128 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 136 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 137 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 129 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 138 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 130 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 139 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 131 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 140 | + |
| 132 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 141 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 133 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 142 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 143 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 134 | asc_vf_call<asc_loadalign_unpack4_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); | 144 | asc_vf_call<asc_loadalign_unpack4_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 135 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 145 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 136 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 146 | + |
| 147 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 137 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 148 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 149 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 138 | asc_sync(); | 150 | asc_sync(); |
| 139 | } | 151 | } |
| 140 | } // namespace | 152 | } // namespace |
| 141 | 153 | ||
| 142 | int main() | 154 | int main() |
| 143 | { | 155 | { |
| 144 | - std::vector<uint8_t> input(INPUT_ELEMENTS); | 156 | + std::vector<uint8_t> input(INPUT_STORAGE_ELEMENTS, 0); |
| 145 | std::vector<uint8_t> output(OUTPUT_ELEMENTS, 0xff); | 157 | std::vector<uint8_t> output(OUTPUT_ELEMENTS, 0xff); |
| 146 | std::vector<uint8_t> golden(OUTPUT_ELEMENTS, 0); | 158 | std::vector<uint8_t> golden(OUTPUT_ELEMENTS, 0); |
| 147 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); | 159 | for (uint16_t i = 0; i < INPUT_ELEMENTS; ++i) input[i] = static_cast<uint8_t>(i % 251 + 1); |
| @@ -99,27 +99,35 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 99 | #include <iostream> | 99 | #include <iostream> |
| 100 | #include <vector> | 100 | #include <vector> |
| 101 | #include "c_api/asc_simd.h" | 101 | #include "c_api/asc_simd.h" |
| 102 | +#include "utils/std/cmath.h" | ||
| 102 | #include "acl/acl.h" | 103 | #include "acl/acl.h" |
| 103 | 104 | ||
| 104 | namespace { | 105 | namespace { |
| 105 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 106 | +constexpr uint8_t MUTEX_ID = 0; |
| 106 | -{ | ||
| 107 | - return (numerator + denominator - 1) / denominator; | ||
| 108 | -} | ||
| 109 | 107 | ||
| 110 | -constexpr uint32_t INPUT_ELEMENTS = 256; | 108 | +constexpr uint32_t INPUT_ELEMENTS = 260; |
| 111 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 109 | +constexpr uint32_t OUTPUT_ELEMENTS = 520; |
| 112 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 110 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); |
| 113 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 111 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 112 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 113 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 114 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 115 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 116 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 128; | ||
| 114 | 117 | ||
| 118 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 119 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 120 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 115 | __simd_vf__ inline void asc_loadalign_unpack_postupdate_vf(__ubuf__ uint8_t* output, | 121 | __simd_vf__ inline void asc_loadalign_unpack_postupdate_vf(__ubuf__ uint8_t* output, |
| 116 | __ubuf__ uint8_t* input, | 122 | __ubuf__ uint8_t* input, |
| 117 | - uint16_t one_repeat_size, uint16_t repeat_time) | 123 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 118 | { | 124 | { |
| 119 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 125 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 126 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 120 | vector_uint8_t dst_reg; | 127 | vector_uint8_t dst_reg; |
| 121 | __ubuf__ uint8_t* src = input; | 128 | __ubuf__ uint8_t* src = input; |
| 122 | for (uint16_t i = 0; i < repeat_time; ++i) { | 129 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 130 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 123 | asc_loadalign_unpack_postupdate(dst_reg, src, 128); | 131 | asc_loadalign_unpack_postupdate(dst_reg, src, 128); |
| 124 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 132 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 125 | } | 133 | } |
| @@ -128,17 +136,21 @@ __simd_vf__ inline void asc_loadalign_unpack_postupdate_vf(__ubuf__ uint8_t* out | |||
| 128 | __global__ __vector__ void asc_loadalign_unpack_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 136 | __global__ __vector__ void asc_loadalign_unpack_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 129 | { | 137 | { |
| 130 | asc_init(); | 138 | asc_init(); |
| 131 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 139 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 132 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 140 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 141 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 133 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 142 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 134 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 143 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 135 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 144 | + |
| 136 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 145 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 137 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 146 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 147 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 138 | asc_vf_call<asc_loadalign_unpack_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); | 148 | asc_vf_call<asc_loadalign_unpack_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 139 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 149 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 140 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 150 | + |
| 151 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 141 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 152 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 153 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 142 | asc_sync(); | 154 | asc_sync(); |
| 143 | } | 155 | } |
| 144 | } // namespace | 156 | } // namespace |
| @@ -196,25 +196,33 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 196 | #include <iostream> | 196 | #include <iostream> |
| 197 | #include <vector> | 197 | #include <vector> |
| 198 | #include "c_api/asc_simd.h" | 198 | #include "c_api/asc_simd.h" |
| 199 | +#include "utils/std/cmath.h" | ||
| 199 | #include "acl/acl.h" | 200 | #include "acl/acl.h" |
| 200 | 201 | ||
| 201 | namespace { | 202 | namespace { |
| 202 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 203 | +constexpr uint8_t MUTEX_ID = 0; |
| 203 | -{ | ||
| 204 | - return (numerator + denominator - 1) / denominator; | ||
| 205 | -} | ||
| 206 | 204 | ||
| 207 | -constexpr uint32_t INPUT_ELEMENTS = 256; | 205 | +constexpr uint32_t INPUT_ELEMENTS = 260; |
| 208 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 206 | +constexpr uint32_t OUTPUT_ELEMENTS = 520; |
| 209 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 207 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); |
| 210 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 208 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 209 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 210 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 211 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 212 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 213 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 128; | ||
| 211 | 214 | ||
| 215 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 216 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 217 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 212 | __simd_vf__ inline void asc_loadalign_upsample_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, | 218 | __simd_vf__ inline void asc_loadalign_upsample_vf(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, |
| 213 | - uint16_t one_repeat_size, uint16_t repeat_time) | 219 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 214 | { | 220 | { |
| 215 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 221 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 222 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 216 | vector_uint8_t dst_reg; | 223 | vector_uint8_t dst_reg; |
| 217 | for (uint16_t i = 0; i < repeat_time; ++i) { | 224 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 225 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 218 | asc_loadalign_upsample(dst_reg, input + i * 128); | 226 | asc_loadalign_upsample(dst_reg, input + i * 128); |
| 219 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 227 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 220 | } | 228 | } |
| @@ -223,17 +231,21 @@ __simd_vf__ inline void asc_loadalign_upsample_vf(__ubuf__ uint8_t* output, __ub | |||
| 223 | __global__ __vector__ void asc_loadalign_upsample_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 231 | __global__ __vector__ void asc_loadalign_upsample_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 224 | { | 232 | { |
| 225 | asc_init(); | 233 | asc_init(); |
| 226 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 234 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 227 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 235 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 236 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 228 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 237 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 229 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 238 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 230 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 239 | + |
| 231 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 240 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 232 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 241 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 242 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 233 | asc_vf_call<asc_loadalign_upsample_vf>(output_local, input_local, one_repeat_size, repeat_time); | 243 | asc_vf_call<asc_loadalign_upsample_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 234 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 244 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 235 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 245 | + |
| 246 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 236 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 247 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 248 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 237 | asc_sync(); | 249 | asc_sync(); |
| 238 | } | 250 | } |
| 239 | } // namespace | 251 | } // namespace |
| @@ -107,27 +107,35 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 107 | #include <iostream> | 107 | #include <iostream> |
| 108 | #include <vector> | 108 | #include <vector> |
| 109 | #include "c_api/asc_simd.h" | 109 | #include "c_api/asc_simd.h" |
| 110 | +#include "utils/std/cmath.h" | ||
| 110 | #include "acl/acl.h" | 111 | #include "acl/acl.h" |
| 111 | 112 | ||
| 112 | namespace { | 113 | namespace { |
| 113 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 114 | +constexpr uint8_t MUTEX_ID = 0; |
| 114 | -{ | ||
| 115 | - return (numerator + denominator - 1) / denominator; | ||
| 116 | -} | ||
| 117 | 115 | ||
| 118 | -constexpr uint32_t INPUT_ELEMENTS = 256; | 116 | +constexpr uint32_t INPUT_ELEMENTS = 260; |
| 119 | -constexpr uint32_t OUTPUT_ELEMENTS = 512; | 117 | +constexpr uint32_t OUTPUT_ELEMENTS = 520; |
| 120 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); | 118 | constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t); |
| 121 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); | 119 | constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t); |
| 120 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; | ||
| 121 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 122 | +constexpr uint32_t REPEAT_COUNT = AscendC::Std::ceil_div(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER); | ||
| 123 | +constexpr uint32_t OUTPUT_STORAGE_ELEMENTS = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 124 | +constexpr uint32_t INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 128; | ||
| 122 | 125 | ||
| 126 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 127 | +constexpr uint32_t TOTAL_LENGTH = OUTPUT_ELEMENTS; | ||
| 128 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 123 | __simd_vf__ inline void asc_loadalign_upsample_postupdate_vf(__ubuf__ uint8_t* output, | 129 | __simd_vf__ inline void asc_loadalign_upsample_postupdate_vf(__ubuf__ uint8_t* output, |
| 124 | __ubuf__ uint8_t* input, | 130 | __ubuf__ uint8_t* input, |
| 125 | - uint16_t one_repeat_size, uint16_t repeat_time) | 131 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 126 | { | 132 | { |
| 127 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | 133 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 134 | + uint32_t remaining_length = OUTPUT_ELEMENTS; | ||
| 128 | vector_uint8_t dst_reg; | 135 | vector_uint8_t dst_reg; |
| 129 | __ubuf__ uint8_t* src = input; | 136 | __ubuf__ uint8_t* src = input; |
| 130 | for (uint16_t i = 0; i < repeat_time; ++i) { | 137 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 138 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 131 | asc_loadalign_upsample_postupdate(dst_reg, src, 128); | 139 | asc_loadalign_upsample_postupdate(dst_reg, src, 128); |
| 132 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); | 140 | asc_storealign(output + i * one_repeat_size, dst_reg, mask); |
| 133 | } | 141 | } |
| @@ -136,17 +144,21 @@ __simd_vf__ inline void asc_loadalign_upsample_postupdate_vf(__ubuf__ uint8_t* o | |||
| 136 | __global__ __vector__ void asc_loadalign_upsample_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 144 | __global__ __vector__ void asc_loadalign_upsample_postupdate_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 137 | { | 145 | { |
| 138 | asc_init(); | 146 | asc_init(); |
| 139 | - __ubuf__ uint8_t input_local[INPUT_ELEMENTS]; | 147 | + __ubuf__ uint8_t input_local[INPUT_STORAGE_ELEMENTS]; |
| 140 | - __ubuf__ uint8_t output_local[OUTPUT_ELEMENTS]; | 148 | + __ubuf__ uint8_t output_local[OUTPUT_STORAGE_ELEMENTS]; |
| 149 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 141 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); | 150 | asc_copy_gm2ub_align(input_local, input, INPUT_BYTES); |
| 142 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 151 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 143 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 152 | + |
| 144 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 153 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 145 | - uint16_t repeat_time = ceil_division(OUTPUT_ELEMENTS, one_repeat_size); | 154 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 155 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 146 | asc_vf_call<asc_loadalign_upsample_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); | 156 | asc_vf_call<asc_loadalign_upsample_postupdate_vf>(output_local, input_local, one_repeat_size, repeat_time); |
| 147 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 157 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 148 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 158 | + |
| 159 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 149 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); | 160 | asc_copy_ub2gm_align(output, output_local, OUTPUT_BYTES); |
| 161 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 150 | asc_sync(); | 162 | asc_sync(); |
| 151 | } | 163 | } |
| 152 | } // namespace | 164 | } // namespace |
| @@ -94,30 +94,37 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 94 | #include <iostream> | 94 | #include <iostream> |
| 95 | #include <vector> | 95 | #include <vector> |
| 96 | #include "c_api/asc_simd.h" | 96 | #include "c_api/asc_simd.h" |
| 97 | +#include "utils/std/cmath.h" | ||
| 97 | #include "acl/acl.h" | 98 | #include "acl/acl.h" |
| 98 | 99 | ||
| 99 | namespace { | 100 | namespace { |
| 100 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 101 | +constexpr uint8_t MUTEX_ID = 0; |
| 101 | -{ | ||
| 102 | - return (numerator + denominator - 1) / denominator; | ||
| 103 | -} | ||
| 104 | 102 | ||
| 105 | -constexpr uint32_t DATA_ELEMENTS = 512; | 103 | +constexpr uint32_t DATA_ELEMENTS = 517; |
| 106 | -constexpr uint32_t BUFFER_ELEMENTS = DATA_ELEMENTS + 32; | 104 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; |
| 105 | +constexpr uint32_t PADDED_DATA_ELEMENTS = | ||
| 106 | + AscendC::Std::ceil_div(DATA_ELEMENTS, ELEMENTS_PER_REGISTER) * ELEMENTS_PER_REGISTER; | ||
| 107 | +constexpr uint32_t BUFFER_ELEMENTS = PADDED_DATA_ELEMENTS + 32; | ||
| 107 | constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t); | 108 | constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t); |
| 108 | 109 | ||
| 110 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 111 | +constexpr uint32_t TOTAL_LENGTH = DATA_ELEMENTS; | ||
| 112 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 109 | __simd_vf__ inline void asc_loadunalign_vf(__ubuf__ uint8_t* dst, __ubuf__ uint8_t* src, | 113 | __simd_vf__ inline void asc_loadunalign_vf(__ubuf__ uint8_t* dst, __ubuf__ uint8_t* src, |
| 110 | - uint16_t one_repeat_size, uint16_t repeat_time) | 114 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 111 | { | 115 | { |
| 112 | vector_load_unalign load_unalign_reg; | 116 | vector_load_unalign load_unalign_reg; |
| 113 | vector_store_unalign store_unalign_reg; | 117 | vector_store_unalign store_unalign_reg; |
| 114 | vector_uint8_t dst_reg; | 118 | vector_uint8_t dst_reg; |
| 115 | asc_loadunalign_pre(load_unalign_reg, src); | 119 | asc_loadunalign_pre(load_unalign_reg, src); |
| 120 | + uint32_t remaining = DATA_ELEMENTS; | ||
| 116 | for (uint16_t i = 0; i < repeat_time; ++i) { | 121 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 122 | + const uint16_t valid_count = remaining > one_repeat_size ? one_repeat_size : remaining; | ||
| 117 | asc_loadunalign(dst_reg, load_unalign_reg, src + i * one_repeat_size); | 123 | asc_loadunalign(dst_reg, load_unalign_reg, src + i * one_repeat_size); |
| 118 | - asc_storeunalign(dst + i * one_repeat_size, store_unalign_reg, dst_reg, one_repeat_size); | 124 | + asc_storeunalign(dst + i * one_repeat_size, store_unalign_reg, dst_reg, valid_count); |
| 125 | + remaining -= valid_count; | ||
| 119 | } | 126 | } |
| 120 | - asc_storeunalign_post(dst, store_unalign_reg, repeat_time * one_repeat_size); | 127 | + asc_storeunalign_post(dst, store_unalign_reg, DATA_ELEMENTS); |
| 121 | } | 128 | } |
| 122 | 129 | ||
| 123 | __global__ __vector__ void asc_loadunalign_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) | 130 | __global__ __vector__ void asc_loadunalign_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| @@ -125,15 +132,19 @@ __global__ __vector__ void asc_loadunalign_kernel(__gm__ uint8_t* output, __gm__ | |||
| 125 | asc_init(); | 132 | asc_init(); |
| 126 | __ubuf__ uint8_t input_local[BUFFER_ELEMENTS]; | 133 | __ubuf__ uint8_t input_local[BUFFER_ELEMENTS]; |
| 127 | __ubuf__ uint8_t output_local[BUFFER_ELEMENTS]; | 134 | __ubuf__ uint8_t output_local[BUFFER_ELEMENTS]; |
| 135 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 128 | asc_copy_gm2ub_align(input_local, input, BUFFER_BYTES); | 136 | asc_copy_gm2ub_align(input_local, input, BUFFER_BYTES); |
| 129 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 137 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 130 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 138 | + |
| 131 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 139 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 132 | - uint16_t repeat_time = ceil_division(DATA_ELEMENTS, one_repeat_size); | 140 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 141 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 133 | asc_vf_call<asc_loadunalign_vf>(output_local + 1, input_local + 1, one_repeat_size, repeat_time); | 142 | asc_vf_call<asc_loadunalign_vf>(output_local + 1, input_local + 1, one_repeat_size, repeat_time); |
| 134 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 143 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 135 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 144 | + |
| 145 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 136 | asc_copy_ub2gm_align(output, output_local, BUFFER_BYTES); | 146 | asc_copy_ub2gm_align(output, output_local, BUFFER_BYTES); |
| 147 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 137 | asc_sync(); | 148 | asc_sync(); |
| 138 | } | 149 | } |
| 139 | } // namespace | 150 | } // namespace |
| @@ -172,29 +172,36 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 172 | #include <iostream> | 172 | #include <iostream> |
| 173 | #include <vector> | 173 | #include <vector> |
| 174 | #include "c_api/asc_simd.h" | 174 | #include "c_api/asc_simd.h" |
| 175 | +#include "utils/std/cmath.h" | ||
| 175 | #include "acl/acl.h" | 176 | #include "acl/acl.h" |
| 176 | 177 | ||
| 177 | namespace { | 178 | namespace { |
| 178 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 179 | +constexpr uint8_t MUTEX_ID = 0; |
| 179 | -{ | ||
| 180 | - return (numerator + denominator - 1) / denominator; | ||
| 181 | -} | ||
| 182 | 180 | ||
| 183 | -constexpr uint32_t DATA_ELEMENTS = 512; | 181 | +constexpr uint32_t DATA_ELEMENTS = 260; |
| 184 | -constexpr uint32_t BUFFER_ELEMENTS = DATA_ELEMENTS + 32; | 182 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; |
| 183 | +constexpr uint32_t PADDED_DATA_ELEMENTS = | ||
| 184 | + AscendC::Std::ceil_div(DATA_ELEMENTS, ELEMENTS_PER_REGISTER) * ELEMENTS_PER_REGISTER; | ||
| 185 | +constexpr uint32_t BUFFER_ELEMENTS = PADDED_DATA_ELEMENTS + 32; | ||
| 185 | constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t); | 186 | constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t); |
| 186 | 187 | ||
| 188 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 189 | +constexpr uint32_t TOTAL_LENGTH = DATA_ELEMENTS; | ||
| 190 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 187 | __simd_vf__ inline void asc_loadunalign_postupdate_vf(__ubuf__ uint8_t* dst, | 191 | __simd_vf__ inline void asc_loadunalign_postupdate_vf(__ubuf__ uint8_t* dst, |
| 188 | __ubuf__ uint8_t* src, | 192 | __ubuf__ uint8_t* src, |
| 189 | - uint16_t one_repeat_size, uint16_t repeat_time) | 193 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 190 | { | 194 | { |
| 191 | vector_load_unalign load_unalign_reg; | 195 | vector_load_unalign load_unalign_reg; |
| 192 | vector_store_unalign store_unalign_reg; | 196 | vector_store_unalign store_unalign_reg; |
| 193 | vector_uint8_t dst_reg; | 197 | vector_uint8_t dst_reg; |
| 194 | asc_loadunalign_pre(load_unalign_reg, src); | 198 | asc_loadunalign_pre(load_unalign_reg, src); |
| 199 | + uint32_t remaining = DATA_ELEMENTS; | ||
| 195 | for (uint16_t i = 0; i < repeat_time; ++i) { | 200 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 196 | - asc_loadunalign_postupdate(dst_reg, load_unalign_reg, src, one_repeat_size); | 201 | + const uint16_t valid_count = remaining > one_repeat_size ? one_repeat_size : remaining; |
| 197 | - asc_storeunalign_postupdate(dst, store_unalign_reg, dst_reg, one_repeat_size); | 202 | + asc_loadunalign_postupdate(dst_reg, load_unalign_reg, src, valid_count); |
| 203 | + asc_storeunalign_postupdate(dst, store_unalign_reg, dst_reg, valid_count); | ||
| 204 | + remaining -= valid_count; | ||
| 198 | } | 205 | } |
| 199 | asc_storeunalign_post_postupdate(dst, store_unalign_reg, 0); | 206 | asc_storeunalign_post_postupdate(dst, store_unalign_reg, 0); |
| 200 | } | 207 | } |
| @@ -204,16 +211,20 @@ __global__ __vector__ void asc_loadunalign_postupdate_kernel(__gm__ uint8_t* out | |||
| 204 | asc_init(); | 211 | asc_init(); |
| 205 | __ubuf__ uint8_t input_local[BUFFER_ELEMENTS]; | 212 | __ubuf__ uint8_t input_local[BUFFER_ELEMENTS]; |
| 206 | __ubuf__ uint8_t output_local[BUFFER_ELEMENTS]; | 213 | __ubuf__ uint8_t output_local[BUFFER_ELEMENTS]; |
| 214 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 207 | asc_copy_gm2ub_align(input_local, input, BUFFER_BYTES); | 215 | asc_copy_gm2ub_align(input_local, input, BUFFER_BYTES); |
| 208 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 216 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 209 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 217 | + |
| 210 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 218 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 211 | - uint16_t repeat_time = ceil_division(DATA_ELEMENTS, one_repeat_size); | 219 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 220 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 212 | asc_vf_call<asc_loadunalign_postupdate_vf>( | 221 | asc_vf_call<asc_loadunalign_postupdate_vf>( |
| 213 | output_local + 1, input_local + 1, one_repeat_size, repeat_time); | 222 | output_local + 1, input_local + 1, one_repeat_size, repeat_time); |
| 214 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 223 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 215 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 224 | + |
| 225 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 216 | asc_copy_ub2gm_align(output, output_local, BUFFER_BYTES); | 226 | asc_copy_ub2gm_align(output, output_local, BUFFER_BYTES); |
| 227 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 217 | asc_sync(); | 228 | asc_sync(); |
| 218 | } | 229 | } |
| 219 | } // namespace | 230 | } // namespace |
| @@ -163,29 +163,36 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 163 | #include <iostream> | 163 | #include <iostream> |
| 164 | #include <vector> | 164 | #include <vector> |
| 165 | #include "c_api/asc_simd.h" | 165 | #include "c_api/asc_simd.h" |
| 166 | +#include "utils/std/cmath.h" | ||
| 166 | #include "acl/acl.h" | 167 | #include "acl/acl.h" |
| 167 | 168 | ||
| 168 | namespace { | 169 | namespace { |
| 169 | -__aicore__ constexpr uint32_t ceil_division(uint32_t numerator, uint32_t denominator) | 170 | +constexpr uint8_t MUTEX_ID = 0; |
| 170 | -{ | ||
| 171 | - return (numerator + denominator - 1) / denominator; | ||
| 172 | -} | ||
| 173 | 171 | ||
| 174 | -constexpr uint32_t DATA_ELEMENTS = 512; | 172 | +constexpr uint32_t DATA_ELEMENTS = 260; |
| 175 | -constexpr uint32_t BUFFER_ELEMENTS = DATA_ELEMENTS + 32; | 173 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 256; |
| 174 | +constexpr uint32_t PADDED_DATA_ELEMENTS = | ||
| 175 | + AscendC::Std::ceil_div(DATA_ELEMENTS, ELEMENTS_PER_REGISTER) * ELEMENTS_PER_REGISTER; | ||
| 176 | +constexpr uint32_t BUFFER_ELEMENTS = PADDED_DATA_ELEMENTS + 32; | ||
| 176 | constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t); | 177 | constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t); |
| 177 | 178 | ||
| 179 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 180 | +constexpr uint32_t TOTAL_LENGTH = DATA_ELEMENTS; | ||
| 181 | +constexpr uint32_t DATA_BYTES = TOTAL_LENGTH * sizeof(uint8_t); | ||
| 178 | __simd_vf__ inline void asc_loadunalign_pre_vf(__ubuf__ uint8_t* dst, | 182 | __simd_vf__ inline void asc_loadunalign_pre_vf(__ubuf__ uint8_t* dst, |
| 179 | __ubuf__ uint8_t* src, | 183 | __ubuf__ uint8_t* src, |
| 180 | - uint16_t one_repeat_size, uint16_t repeat_time) | 184 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 181 | { | 185 | { |
| 182 | vector_load_unalign load_unalign_reg; | 186 | vector_load_unalign load_unalign_reg; |
| 183 | vector_store_unalign store_unalign_reg; | 187 | vector_store_unalign store_unalign_reg; |
| 184 | vector_uint8_t dst_reg; | 188 | vector_uint8_t dst_reg; |
| 185 | asc_loadunalign_pre(load_unalign_reg, src); | 189 | asc_loadunalign_pre(load_unalign_reg, src); |
| 190 | + uint32_t remaining = DATA_ELEMENTS; | ||
| 186 | for (uint16_t i = 0; i < repeat_time; ++i) { | 191 | for (uint16_t i = 0; i < repeat_time; ++i) { |
| 187 | - asc_loadunalign_postupdate(dst_reg, load_unalign_reg, src, one_repeat_size); | 192 | + const uint16_t valid_count = remaining > one_repeat_size ? one_repeat_size : remaining; |
| 188 | - asc_storeunalign_postupdate(dst, store_unalign_reg, dst_reg, one_repeat_size); | 193 | + asc_loadunalign_postupdate(dst_reg, load_unalign_reg, src, valid_count); |
| 194 | + asc_storeunalign_postupdate(dst, store_unalign_reg, dst_reg, valid_count); | ||
| 195 | + remaining -= valid_count; | ||
| 189 | } | 196 | } |
| 190 | asc_storeunalign_post_postupdate(dst, store_unalign_reg, 0); | 197 | asc_storeunalign_post_postupdate(dst, store_unalign_reg, 0); |
| 191 | } | 198 | } |
| @@ -195,15 +202,19 @@ __global__ __vector__ void asc_loadunalign_pre_kernel(__gm__ uint8_t* output, __ | |||
| 195 | asc_init(); | 202 | asc_init(); |
| 196 | __ubuf__ uint8_t input_local[BUFFER_ELEMENTS]; | 203 | __ubuf__ uint8_t input_local[BUFFER_ELEMENTS]; |
| 197 | __ubuf__ uint8_t output_local[BUFFER_ELEMENTS]; | 204 | __ubuf__ uint8_t output_local[BUFFER_ELEMENTS]; |
| 205 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 198 | asc_copy_gm2ub_align(input_local, input, BUFFER_BYTES); | 206 | asc_copy_gm2ub_align(input_local, input, BUFFER_BYTES); |
| 199 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 207 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 200 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 208 | + |
| 201 | - uint16_t one_repeat_size = asc_get_vf_len() / sizeof(uint8_t); | 209 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 202 | - uint16_t repeat_time = ceil_division(DATA_ELEMENTS, one_repeat_size); | 210 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 211 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 203 | asc_vf_call<asc_loadunalign_pre_vf>(output_local + 1, input_local + 1, one_repeat_size, repeat_time); | 212 | asc_vf_call<asc_loadunalign_pre_vf>(output_local + 1, input_local + 1, one_repeat_size, repeat_time); |
| 204 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 213 | + asc_unlock(PIPE_V, MUTEX_ID); |
| 205 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 214 | + |
| 215 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 206 | asc_copy_ub2gm_align(output, output_local, BUFFER_BYTES); | 216 | asc_copy_ub2gm_align(output, output_local, BUFFER_BYTES); |
| 217 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 207 | asc_sync(); | 218 | asc_sync(); |
| 208 | } | 219 | } |
| 209 | } // namespace | 220 | } // namespace |
| @@ -132,9 +132,13 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 132 | #include <iostream> | 132 | #include <iostream> |
| 133 | #include <vector> | 133 | #include <vector> |
| 134 | #include "c_api/asc_simd.h" | 134 | #include "c_api/asc_simd.h" |
| 135 | +#include "utils/std/cmath.h" | ||
| 135 | #include "acl/acl.h" | 136 | #include "acl/acl.h" |
| 136 | 137 | ||
| 137 | namespace { | 138 | namespace { |
| 139 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 140 | + | ||
| 141 | + | ||
| 138 | template <typename T> | 142 | template <typename T> |
| 139 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) | 143 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) |
| 140 | { | 144 | { |
| @@ -148,43 +152,53 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 148 | } | 152 | } |
| 149 | 153 | ||
| 150 | constexpr uint16_t ONE_REPEAT_SIZE = 256; | 154 | constexpr uint16_t ONE_REPEAT_SIZE = 256; |
| 151 | -constexpr uint16_t REPEAT_COUNT = 4; | 155 | +constexpr uint32_t DATA_BYTES = 523; |
| 156 | +constexpr uint16_t REPEAT_COUNT = (DATA_BYTES + ONE_REPEAT_SIZE - 1) / ONE_REPEAT_SIZE; | ||
| 152 | constexpr uint32_t TOTAL_BYTES = ONE_REPEAT_SIZE * REPEAT_COUNT; | 157 | constexpr uint32_t TOTAL_BYTES = ONE_REPEAT_SIZE * REPEAT_COUNT; |
| 153 | 158 | ||
| 159 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 160 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(uint8_t); | ||
| 154 | __simd_vf__ inline void exercise(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, | 161 | __simd_vf__ inline void exercise(__ubuf__ uint8_t* output, __ubuf__ uint8_t* input, |
| 155 | - uint16_t oneRepeatSize, uint16_t repeatTimes) | 162 | + uint32_t one_repeat_size, uint16_t repeat_time) |
| 156 | { | 163 | { |
| 157 | - vector_bool mask = asc_create_mask_b8(PAT_ALL); | ||
| 158 | vector_uint8_t value; | 164 | vector_uint8_t value; |
| 159 | addr_reg offset_reg; | 165 | addr_reg offset_reg; |
| 160 | - for (uint16_t i = 0; i < repeatTimes; ++i) { | 166 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 161 | - offset_reg = asc_update_addr_reg_b8(oneRepeatSize); | 167 | + uint32_t remaining_length = DATA_BYTES; |
| 168 | + for (uint16_t i = 0; i < repeat_time; ++i) { | ||
| 169 | + vector_bool mask = asc_update_mask_b8(remaining_length); | ||
| 170 | + offset_reg = asc_update_addr_reg_b8(one_repeat_size); | ||
| 162 | asc_loadalign(value, input, offset_reg); | 171 | asc_loadalign(value, input, offset_reg); |
| 163 | asc_storealign(output, value, offset_reg, mask); | 172 | asc_storealign(output, value, offset_reg, mask); |
| 164 | } | 173 | } |
| 165 | } | 174 | } |
| 166 | 175 | ||
| 167 | -__global__ __vector__ void asc_update_addr_reg_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input, | 176 | +__global__ __vector__ void asc_update_addr_reg_kernel(__gm__ uint8_t* output, __gm__ uint8_t* input) |
| 168 | - uint16_t oneRepeatSize, uint16_t repeatTimes) | ||
| 169 | { | 177 | { |
| 170 | asc_init(); | 178 | asc_init(); |
| 171 | __ubuf__ uint8_t output_local[TOTAL_BYTES]; | 179 | __ubuf__ uint8_t output_local[TOTAL_BYTES]; |
| 172 | __ubuf__ uint8_t input_local[TOTAL_BYTES]; | 180 | __ubuf__ uint8_t input_local[TOTAL_BYTES]; |
| 181 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 173 | asc_copy_gm2ub_align(input_local, input, TOTAL_BYTES); | 182 | asc_copy_gm2ub_align(input_local, input, TOTAL_BYTES); |
| 174 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 183 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 175 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 184 | + |
| 176 | - exercise(output_local, input_local, oneRepeatSize, repeatTimes); | 185 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint8_t)); |
| 177 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 186 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 178 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 187 | + asc_lock(PIPE_V, MUTEX_ID); |
| 188 | + asc_vf_call<exercise>(output_local, input_local, one_repeat_size, repeat_time); | ||
| 189 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 190 | + | ||
| 191 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 179 | asc_copy_ub2gm_align(output, output_local, TOTAL_BYTES); | 192 | asc_copy_ub2gm_align(output, output_local, TOTAL_BYTES); |
| 193 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 180 | asc_sync(); | 194 | asc_sync(); |
| 181 | } | 195 | } |
| 182 | } // namespace | 196 | } // namespace |
| 183 | 197 | ||
| 184 | int main() | 198 | int main() |
| 185 | { | 199 | { |
| 186 | - std::vector<uint8_t> input(TOTAL_BYTES), output(TOTAL_BYTES, 0xff), golden(TOTAL_BYTES); | 200 | + std::vector<uint8_t> input(TOTAL_BYTES, 0), output(TOTAL_BYTES, 0xff), golden(TOTAL_BYTES, 0xff); |
| 187 | - for (uint32_t i = 0; i < TOTAL_BYTES; ++i) input[i] = static_cast<uint8_t>(i % 251); | 201 | + for (uint32_t i = 0; i < DATA_BYTES; ++i) input[i] = static_cast<uint8_t>(i % 251); |
| 188 | golden = input; | 202 | golden = input; |
| 189 | aclInit(nullptr); | 203 | aclInit(nullptr); |
| 190 | aclrtSetDevice(0); | 204 | aclrtSetDevice(0); |
| @@ -196,11 +210,12 @@ int main() | |||
| 196 | ACL_MEM_MALLOC_HUGE_FIRST); | 210 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 197 | aclrtMemcpy(input_device, input.size() * sizeof(uint8_t), input.data(), input.size() * sizeof(uint8_t), | 211 | aclrtMemcpy(input_device, input.size() * sizeof(uint8_t), input.data(), input.size() * sizeof(uint8_t), |
| 198 | ACL_MEMCPY_HOST_TO_DEVICE); | 212 | ACL_MEMCPY_HOST_TO_DEVICE); |
| 199 | - asc_update_addr_reg_kernel<<<1, 0>>>(output_device, input_device, ONE_REPEAT_SIZE, REPEAT_COUNT); | 213 | + asc_update_addr_reg_kernel<<<1, 0>>>(output_device, input_device); |
| 200 | aclrtSynchronizeDevice(); | 214 | aclrtSynchronizeDevice(); |
| 201 | aclrtMemcpy(output.data(), output.size() * sizeof(uint8_t), output_device, output.size() * sizeof(uint8_t), | 215 | aclrtMemcpy(output.data(), output.size() * sizeof(uint8_t), output_device, output.size() * sizeof(uint8_t), |
| 202 | ACL_MEMCPY_DEVICE_TO_HOST); | 216 | ACL_MEMCPY_DEVICE_TO_HOST); |
| 203 | - const bool passed = compare_data(output, golden); | 217 | + bool passed = true; |
| 218 | + for (uint32_t i = 0; i < DATA_BYTES; ++i) passed = passed && output[i] == golden[i]; | ||
| 204 | std::cout << (passed ? "[Success] asc_update_addr_reg_b8 passed." : "[Failed] asc_update_addr_reg_b8 failed.") << std::endl; | 219 | std::cout << (passed ? "[Success] asc_update_addr_reg_b8 passed." : "[Failed] asc_update_addr_reg_b8 failed.") << std::endl; |
| 205 | aclrtFree(input_device); | 220 | aclrtFree(input_device); |
| 206 | aclrtFree(output_device); | 221 | aclrtFree(output_device); |
| @@ -115,9 +115,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 115 | #include <vector> | 115 | #include <vector> |
| 116 | 116 | ||
| 117 | #include "c_api/asc_simd.h" | 117 | #include "c_api/asc_simd.h" |
| 118 | +#include "utils/std/cmath.h" | ||
| 118 | #include "acl/acl.h" | 119 | #include "acl/acl.h" |
| 119 | 120 | ||
| 120 | namespace { | 121 | namespace { |
| 122 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 123 | + | ||
| 121 | template <typename T> | 124 | template <typename T> |
| 122 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) | 125 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) |
| 123 | { | 126 | { |
| @@ -130,31 +133,49 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 130 | return true; | 133 | return true; |
| 131 | } | 134 | } |
| 132 | 135 | ||
| 133 | -constexpr uint32_t ELEMENT_COUNT = 64; | 136 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 137 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(float); | ||
| 138 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 139 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(float); | ||
| 140 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 141 | +constexpr uint32_t REPEAT_COUNT = | ||
| 142 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 143 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 144 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 134 | 145 | ||
| 135 | -__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src) | 146 | +__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src, uint32_t one_repeat_size, uint16_t repeat_time) |
| 136 | { | 147 | { |
| 137 | vector_float dst_reg; | 148 | vector_float dst_reg; |
| 138 | vector_float src_reg; | 149 | vector_float src_reg; |
| 139 | - uint32_t count = ELEMENT_COUNT; | 150 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 140 | - vector_bool mask = asc_update_mask_b32(count); | 151 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 141 | - asc_loadalign(src_reg, src); | 152 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 142 | - asc_abs(dst_reg, src_reg, mask); | 153 | + const uint32_t offset = i * one_repeat_size; |
| 143 | - asc_storealign(dst, dst_reg, mask); | 154 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 155 | + asc_loadalign(src_reg, src + offset); | ||
| 156 | + asc_abs(dst_reg, src_reg, mask); | ||
| 157 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 158 | + } | ||
| 144 | } | 159 | } |
| 145 | 160 | ||
| 146 | __global__ __vector__ void asc_abs_kernel(__gm__ float* dst, __gm__ float* src) | 161 | __global__ __vector__ void asc_abs_kernel(__gm__ float* dst, __gm__ float* src) |
| 147 | { | 162 | { |
| 148 | asc_init(); | 163 | asc_init(); |
| 149 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 164 | + __ubuf__ float dst_local[PADDED_ELEMENT_COUNT]; |
| 150 | - __ubuf__ float src_local[ELEMENT_COUNT]; | 165 | + __ubuf__ float src_local[PADDED_ELEMENT_COUNT]; |
| 151 | - asc_copy_gm2ub_align(src_local, src, ELEMENT_COUNT * sizeof(float)); | 166 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 152 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 167 | + asc_copy_gm2ub_align(src_local, src, TOTAL_LENGTH * sizeof(float)); |
| 153 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 168 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 154 | - compute(dst_local, src_local); | 169 | + |
| 155 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 170 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(float)); |
| 156 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 171 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 157 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 172 | + asc_lock(PIPE_V, MUTEX_ID); |
| 173 | + asc_vf_call<compute>(dst_local, src_local, one_repeat_size, repeat_time); | ||
| 174 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 175 | + | ||
| 176 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 177 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(float)); | ||
| 178 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 158 | asc_sync(); | 179 | asc_sync(); |
| 159 | } | 180 | } |
| 160 | 181 | ||
| @@ -162,20 +183,20 @@ __global__ __vector__ void asc_abs_kernel(__gm__ float* dst, __gm__ float* src) | |||
| 162 | 183 | ||
| 163 | int main() | 184 | int main() |
| 164 | { | 185 | { |
| 165 | - std::vector<float> src(ELEMENT_COUNT); | 186 | + std::vector<float> src(TOTAL_LENGTH); |
| 166 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 187 | + std::vector<float> output(TOTAL_LENGTH, 0.0f); |
| 167 | - std::vector<float> golden(ELEMENT_COUNT); | 188 | + std::vector<float> golden(TOTAL_LENGTH); |
| 168 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 189 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 169 | src[i] = (static_cast<int>(i) - 32) * 0.25f; | 190 | src[i] = (static_cast<int>(i) - 32) * 0.25f; |
| 170 | golden[i] = std::fabs(src[i]); | 191 | golden[i] = std::fabs(src[i]); |
| 171 | } | 192 | } |
| 172 | aclInit(nullptr); | 193 | aclInit(nullptr); |
| 173 | aclrtSetDevice(0); | 194 | aclrtSetDevice(0); |
| 174 | float* src_device = nullptr; | 195 | float* src_device = nullptr; |
| 175 | - aclrtMalloc(reinterpret_cast<void**>(&src_device), (ELEMENT_COUNT) * sizeof(float), | 196 | + aclrtMalloc(reinterpret_cast<void**>(&src_device), (TOTAL_LENGTH) * sizeof(float), |
| 176 | ACL_MEM_MALLOC_HUGE_FIRST); | 197 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 177 | float* dst_device = nullptr; | 198 | float* dst_device = nullptr; |
| 178 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 199 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(float), |
| 179 | ACL_MEM_MALLOC_HUGE_FIRST); | 200 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 180 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), | 201 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), |
| 181 | ACL_MEMCPY_HOST_TO_DEVICE); | 202 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -178,6 +178,7 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 178 | #include <vector> | 178 | #include <vector> |
| 179 | 179 | ||
| 180 | #include "c_api/asc_simd.h" | 180 | #include "c_api/asc_simd.h" |
| 181 | +#include "utils/std/cmath.h" | ||
| 181 | #include "acl/acl.h" | 182 | #include "acl/acl.h" |
| 182 | 183 | ||
| 183 | namespace { | 184 | namespace { |
| @@ -197,36 +198,63 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected) | |||
| 197 | return actual == expected; | 198 | return actual == expected; |
| 198 | } | 199 | } |
| 199 | 200 | ||
| 200 | -constexpr uint32_t ELEMENT_COUNT = 64; | 201 | +// 本示例按256字节的寄存器宽度预留UB空间,每个寄存器可容纳256 / sizeof(int32_t) = 64个元素。 |
| 202 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; | ||
| 203 | +// 选取137个有效元素,覆盖两个完整寄存器和一个仅含9个有效元素的尾块。 | ||
| 204 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(int32_t); | ||
| 205 | +// 将字节数换算为元素数,供循环次数和有效元素掩码计算使用。 | ||
| 206 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(int32_t); | ||
| 207 | +// 向上取整得到3个寄存器块;直接整除只得到2,会漏掉尾块。 | ||
| 208 | +constexpr uint32_t REPEAT_COUNT = | ||
| 209 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 210 | +// UB容量扩展为3 * 64 = 192个元素,保证尾轮整寄存器加载时不越过已分配空间。 | ||
| 211 | +// 额外空间仅用于安全加载,计算和写回的有效范围仍由掩码及TOTAL_LENGTH控制。 | ||
| 212 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 213 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 201 | 214 | ||
| 202 | -__simd_vf__ inline void add_vf(__ubuf__ float* dst, __ubuf__ float* src0, __ubuf__ float* src1) | 215 | +__simd_vf__ inline void add_vf(__ubuf__ int32_t* dst, __ubuf__ int32_t* src0, __ubuf__ int32_t* src1, uint32_t one_repeat_size, uint16_t repeat_time) |
| 203 | { | 216 | { |
| 204 | - vector_float dst_reg; | 217 | + vector_int32_t dst_reg; |
| 205 | - vector_float src0_reg; | 218 | + vector_int32_t src0_reg; |
| 206 | - vector_float src1_reg; | 219 | + vector_int32_t src1_reg; |
| 207 | - uint32_t count = ELEMENT_COUNT; | 220 | + // 记录尚未处理的有效元素数,由asc_update_mask_b32逐轮扣减。 |
| 208 | - vector_bool mask = asc_update_mask_b32(count); | 221 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 209 | - asc_loadalign(src0_reg, src0); | 222 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 210 | - asc_loadalign(src1_reg, src1); | 223 | + // 每轮前进一个寄存器块,offset以int32_t元素为单位,而不是字节。 |
| 211 | - asc_add(dst_reg, src0_reg, src1_reg, mask); | 224 | + const uint32_t offset = i * one_repeat_size; |
| 212 | - asc_storealign(dst, dst_reg, mask); | 225 | + // 三轮分别启用64、64、9个元素;尾轮只计算并存储前9个有效元素。 |
| 226 | + vector_bool mask = asc_update_mask_b32(remaining_length); | ||
| 227 | + asc_loadalign(src0_reg, src0 + offset); | ||
| 228 | + asc_loadalign(src1_reg, src1 + offset); | ||
| 229 | + asc_add(dst_reg, src0_reg, src1_reg, mask); | ||
| 230 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 231 | + } | ||
| 213 | } | 232 | } |
| 214 | 233 | ||
| 215 | -__global__ __vector__ void asc_add_kernel(__gm__ float* dst, __gm__ float* src0, __gm__ float* src1) | 234 | +__global__ __vector__ void asc_add_kernel(__gm__ int32_t* dst, __gm__ int32_t* src0, __gm__ int32_t* src1) |
| 216 | { | 235 | { |
| 217 | asc_init(); | 236 | asc_init(); |
| 218 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 237 | + __ubuf__ int32_t dst_local[PADDED_ELEMENT_COUNT]; |
| 219 | - __ubuf__ float src0_local[ELEMENT_COUNT]; | 238 | + __ubuf__ int32_t src0_local[PADDED_ELEMENT_COUNT]; |
| 220 | - __ubuf__ float src1_local[ELEMENT_COUNT]; | 239 | + __ubuf__ int32_t src1_local[PADDED_ELEMENT_COUNT]; |
| 221 | 240 | ||
| 222 | - asc_copy_gm2ub_align(src0_local, src0, ELEMENT_COUNT * sizeof(float)); | 241 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 223 | - asc_copy_gm2ub_align(src1_local, src1, ELEMENT_COUNT * sizeof(float)); | 242 | + asc_copy_gm2ub_align(src0_local, src0, TOTAL_LENGTH * sizeof(int32_t)); |
| 224 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 243 | + asc_copy_gm2ub_align(src1_local, src1, TOTAL_LENGTH * sizeof(int32_t)); |
| 225 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 244 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 226 | - add_vf(dst_local, src0_local, src1_local); | 245 | + |
| 227 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 246 | + // asc_get_vf_len返回字节数,除以元素字节数得到每轮可处理的元素数(本示例为64)。 |
| 228 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 247 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(int32_t)); |
| 229 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 248 | + // 按实际每轮处理量向上取整:ceil(137 / 64) = 3,确保最后9个元素也被处理。 |
| 249 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); | ||
| 250 | + asc_lock(PIPE_V, MUTEX_ID); | ||
| 251 | + asc_vf_call<add_vf>(dst_local, src0_local, src1_local, one_repeat_size, repeat_time); | ||
| 252 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 253 | + | ||
| 254 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 255 | + // 只搬出137个有效元素,不把UB中为整寄存器加载预留的填充空间写入GM。 | ||
| 256 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(int32_t)); | ||
| 257 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 230 | asc_sync(); | 258 | asc_sync(); |
| 231 | } | 259 | } |
| 232 | 260 | ||
| @@ -234,36 +262,36 @@ __global__ __vector__ void asc_add_kernel(__gm__ float* dst, __gm__ float* src0, | |||
| 234 | 262 | ||
| 235 | int main() | 263 | int main() |
| 236 | { | 264 | { |
| 237 | - std::vector<float> src0(ELEMENT_COUNT); | 265 | + std::vector<int32_t> src0(TOTAL_LENGTH); |
| 238 | - std::vector<float> src1(ELEMENT_COUNT); | 266 | + std::vector<int32_t> src1(TOTAL_LENGTH); |
| 239 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 267 | + std::vector<int32_t> output(TOTAL_LENGTH, 0); |
| 240 | - std::vector<float> golden(ELEMENT_COUNT); | 268 | + std::vector<int32_t> golden(TOTAL_LENGTH); |
| 241 | 269 | ||
| 242 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 270 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 243 | - src0[i] = static_cast<float>(i) * 0.25f; | 271 | + src0[i] = static_cast<int32_t>(i) - 64; |
| 244 | - src1[i] = static_cast<float>(ELEMENT_COUNT - i) * 0.5f; | 272 | + src1[i] = static_cast<int32_t>(TOTAL_LENGTH - i); |
| 245 | golden[i] = src0[i] + src1[i]; | 273 | golden[i] = src0[i] + src1[i]; |
| 246 | } | 274 | } |
| 247 | 275 | ||
| 248 | aclInit(nullptr); | 276 | aclInit(nullptr); |
| 249 | aclrtSetDevice(0); | 277 | aclrtSetDevice(0); |
| 250 | - float* src0_device = nullptr; | 278 | + int32_t* src0_device = nullptr; |
| 251 | - aclrtMalloc(reinterpret_cast<void**>(&src0_device), (ELEMENT_COUNT) * sizeof(float), | 279 | + aclrtMalloc(reinterpret_cast<void**>(&src0_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 252 | ACL_MEM_MALLOC_HUGE_FIRST); | 280 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 253 | - float* src1_device = nullptr; | 281 | + int32_t* src1_device = nullptr; |
| 254 | - aclrtMalloc(reinterpret_cast<void**>(&src1_device), (ELEMENT_COUNT) * sizeof(float), | 282 | + aclrtMalloc(reinterpret_cast<void**>(&src1_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 255 | ACL_MEM_MALLOC_HUGE_FIRST); | 283 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 256 | - float* dst_device = nullptr; | 284 | + int32_t* dst_device = nullptr; |
| 257 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 285 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 258 | ACL_MEM_MALLOC_HUGE_FIRST); | 286 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 259 | - aclrtMemcpy(src0_device, src0.size() * sizeof(float), src0.data(), src0.size() * sizeof(float), | 287 | + aclrtMemcpy(src0_device, src0.size() * sizeof(int32_t), src0.data(), src0.size() * sizeof(int32_t), |
| 260 | ACL_MEMCPY_HOST_TO_DEVICE); | 288 | ACL_MEMCPY_HOST_TO_DEVICE); |
| 261 | - aclrtMemcpy(src1_device, src1.size() * sizeof(float), src1.data(), src1.size() * sizeof(float), | 289 | + aclrtMemcpy(src1_device, src1.size() * sizeof(int32_t), src1.data(), src1.size() * sizeof(int32_t), |
| 262 | ACL_MEMCPY_HOST_TO_DEVICE); | 290 | ACL_MEMCPY_HOST_TO_DEVICE); |
| 263 | 291 | ||
| 264 | asc_add_kernel<<<1, 0>>>(dst_device, src0_device, src1_device); | 292 | asc_add_kernel<<<1, 0>>>(dst_device, src0_device, src1_device); |
| 265 | aclrtSynchronizeDevice(); | 293 | aclrtSynchronizeDevice(); |
| 266 | - aclrtMemcpy(output.data(), output.size() * sizeof(float), dst_device, output.size() * sizeof(float), | 294 | + aclrtMemcpy(output.data(), output.size() * sizeof(int32_t), dst_device, output.size() * sizeof(int32_t), |
| 267 | ACL_MEMCPY_DEVICE_TO_HOST); | 295 | ACL_MEMCPY_DEVICE_TO_HOST); |
| 268 | 296 | ||
| 269 | print_data("Input src0", src0); | 297 | print_data("Input src0", src0); |
| @@ -109,9 +109,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 109 | #include <vector> | 109 | #include <vector> |
| 110 | 110 | ||
| 111 | #include "c_api/asc_simd.h" | 111 | #include "c_api/asc_simd.h" |
| 112 | +#include "utils/std/cmath.h" | ||
| 112 | #include "acl/acl.h" | 113 | #include "acl/acl.h" |
| 113 | 114 | ||
| 114 | namespace { | 115 | namespace { |
| 116 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 117 | + | ||
| 115 | template <typename T> | 118 | template <typename T> |
| 116 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) | 119 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) |
| 117 | { | 120 | { |
| @@ -124,32 +127,50 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 124 | return true; | 127 | return true; |
| 125 | } | 128 | } |
| 126 | 129 | ||
| 127 | -constexpr uint32_t ELEMENT_COUNT = 64; | 130 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 131 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(float); | ||
| 132 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 133 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(float); | ||
| 134 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 135 | +constexpr uint32_t REPEAT_COUNT = | ||
| 136 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 137 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 138 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 128 | constexpr float SCALAR_VALUE = 2.0f; | 139 | constexpr float SCALAR_VALUE = 2.0f; |
| 129 | 140 | ||
| 130 | -__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src) | 141 | +__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src, uint32_t one_repeat_size, uint16_t repeat_time) |
| 131 | { | 142 | { |
| 132 | vector_float dst_reg; | 143 | vector_float dst_reg; |
| 133 | vector_float src_reg; | 144 | vector_float src_reg; |
| 134 | - uint32_t count = ELEMENT_COUNT; | 145 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 135 | - vector_bool mask = asc_update_mask_b32(count); | 146 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 136 | - asc_loadalign(src_reg, src); | 147 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 137 | - asc_add_scalar(dst_reg, src_reg, SCALAR_VALUE, mask); | 148 | + const uint32_t offset = i * one_repeat_size; |
| 138 | - asc_storealign(dst, dst_reg, mask); | 149 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 150 | + asc_loadalign(src_reg, src + offset); | ||
| 151 | + asc_add_scalar(dst_reg, src_reg, SCALAR_VALUE, mask); | ||
| 152 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 153 | + } | ||
| 139 | } | 154 | } |
| 140 | 155 | ||
| 141 | __global__ __vector__ void asc_add_scalar_kernel(__gm__ float* dst, __gm__ float* src) | 156 | __global__ __vector__ void asc_add_scalar_kernel(__gm__ float* dst, __gm__ float* src) |
| 142 | { | 157 | { |
| 143 | asc_init(); | 158 | asc_init(); |
| 144 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 159 | + __ubuf__ float dst_local[PADDED_ELEMENT_COUNT]; |
| 145 | - __ubuf__ float src_local[ELEMENT_COUNT]; | 160 | + __ubuf__ float src_local[PADDED_ELEMENT_COUNT]; |
| 146 | - asc_copy_gm2ub_align(src_local, src, ELEMENT_COUNT * sizeof(float)); | 161 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 147 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 162 | + asc_copy_gm2ub_align(src_local, src, TOTAL_LENGTH * sizeof(float)); |
| 148 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 163 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 149 | - compute(dst_local, src_local); | 164 | + |
| 150 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 165 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(float)); |
| 151 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 166 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 152 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 167 | + asc_lock(PIPE_V, MUTEX_ID); |
| 168 | + asc_vf_call<compute>(dst_local, src_local, one_repeat_size, repeat_time); | ||
| 169 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 170 | + | ||
| 171 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 172 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(float)); | ||
| 173 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 153 | asc_sync(); | 174 | asc_sync(); |
| 154 | } | 175 | } |
| 155 | 176 | ||
| @@ -157,10 +178,10 @@ __global__ __vector__ void asc_add_scalar_kernel(__gm__ float* dst, __gm__ float | |||
| 157 | 178 | ||
| 158 | int main() | 179 | int main() |
| 159 | { | 180 | { |
| 160 | - std::vector<float> src(ELEMENT_COUNT); | 181 | + std::vector<float> src(TOTAL_LENGTH); |
| 161 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 182 | + std::vector<float> output(TOTAL_LENGTH, 0.0f); |
| 162 | - std::vector<float> golden(ELEMENT_COUNT); | 183 | + std::vector<float> golden(TOTAL_LENGTH); |
| 163 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 184 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 164 | src[i] = (static_cast<int>(i) - 16) * 0.25f; | 185 | src[i] = (static_cast<int>(i) - 16) * 0.25f; |
| 165 | golden[i] = src[i] + SCALAR_VALUE; | 186 | golden[i] = src[i] + SCALAR_VALUE; |
| 166 | } | 187 | } |
| @@ -168,10 +189,10 @@ int main() | |||
| 168 | aclInit(nullptr); | 189 | aclInit(nullptr); |
| 169 | aclrtSetDevice(0); | 190 | aclrtSetDevice(0); |
| 170 | float* src_device = nullptr; | 191 | float* src_device = nullptr; |
| 171 | - aclrtMalloc(reinterpret_cast<void**>(&src_device), (ELEMENT_COUNT) * sizeof(float), | 192 | + aclrtMalloc(reinterpret_cast<void**>(&src_device), (TOTAL_LENGTH) * sizeof(float), |
| 172 | ACL_MEM_MALLOC_HUGE_FIRST); | 193 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 173 | float* dst_device = nullptr; | 194 | float* dst_device = nullptr; |
| 174 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 195 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(float), |
| 175 | ACL_MEM_MALLOC_HUGE_FIRST); | 196 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 176 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), | 197 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), |
| 177 | ACL_MEMCPY_HOST_TO_DEVICE); | 198 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -118,9 +118,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 118 | #include <vector> | 118 | #include <vector> |
| 119 | 119 | ||
| 120 | #include "c_api/asc_simd.h" | 120 | #include "c_api/asc_simd.h" |
| 121 | +#include "utils/std/cmath.h" | ||
| 121 | #include "acl/acl.h" | 122 | #include "acl/acl.h" |
| 122 | 123 | ||
| 123 | namespace { | 124 | namespace { |
| 125 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 126 | + | ||
| 124 | template <typename T> | 127 | template <typename T> |
| 125 | void print_data(const char* label, const std::vector<T>& values) | 128 | void print_data(const char* label, const std::vector<T>& values) |
| 126 | { | 129 | { |
| @@ -137,41 +140,60 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected) | |||
| 137 | return actual == expected; | 140 | return actual == expected; |
| 138 | } | 141 | } |
| 139 | 142 | ||
| 140 | -constexpr uint32_t ELEMENT_COUNT = 64; | 143 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 144 | +constexpr uint32_t DATA_BYTES = 133 * sizeof(uint32_t); | ||
| 145 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 146 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(uint32_t); | ||
| 147 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 148 | +constexpr uint32_t REPEAT_COUNT = | ||
| 149 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 150 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 151 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 141 | constexpr uint32_t CARRY_WORDS = 8; | 152 | constexpr uint32_t CARRY_WORDS = 8; |
| 153 | +constexpr uint32_t TOTAL_CARRY_WORDS = REPEAT_COUNT * CARRY_WORDS; | ||
| 142 | 154 | ||
| 143 | -__simd_vf__ inline void addc_vf(__ubuf__ uint32_t* dst, __ubuf__ uint32_t* carry_out, __ubuf__ uint32_t* src0, __ubuf__ uint32_t* src1) | 155 | +__simd_vf__ inline void addc_vf(__ubuf__ uint32_t* dst, __ubuf__ uint32_t* carry_out, __ubuf__ uint32_t* src0, __ubuf__ uint32_t* src1, uint32_t one_repeat_size, uint16_t repeat_time) |
| 144 | { | 156 | { |
| 145 | - vector_uint32_t dst_reg; | 157 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 146 | - vector_uint32_t src0_reg; | 158 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 147 | - vector_uint32_t src1_reg; | 159 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 148 | - vector_bool carry; | 160 | + const uint32_t offset = i * one_repeat_size; |
| 149 | - uint32_t count = ELEMENT_COUNT; | 161 | + vector_uint32_t dst_reg; |
| 150 | - vector_bool mask = asc_update_mask_b32(count); | 162 | + vector_uint32_t src0_reg; |
| 151 | - vector_bool carry_src = mask; | 163 | + vector_uint32_t src1_reg; |
| 152 | - asc_loadalign(src0_reg, src0); | 164 | + vector_bool carry; |
| 153 | - asc_loadalign(src1_reg, src1); | 165 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 154 | - asc_addc(carry, dst_reg, src0_reg, src1_reg, carry_src, mask); | 166 | + vector_bool carry_src = mask; |
| 155 | - asc_storealign(dst, dst_reg, mask); | 167 | + asc_loadalign(src0_reg, src0 + offset); |
| 156 | - asc_storealign(carry_out, carry); | 168 | + asc_loadalign(src1_reg, src1 + offset); |
| 169 | + asc_addc(carry, dst_reg, src0_reg, src1_reg, carry_src, mask); | ||
| 170 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 171 | + asc_storealign(carry_out + offset / ELEMENTS_PER_REGISTER * CARRY_WORDS, carry); | ||
| 172 | + } | ||
| 157 | } | 173 | } |
| 158 | 174 | ||
| 159 | __global__ __vector__ void asc_addc_kernel(__gm__ uint32_t* dst, __gm__ uint32_t* carry, __gm__ uint32_t* src0, __gm__ uint32_t* src1) | 175 | __global__ __vector__ void asc_addc_kernel(__gm__ uint32_t* dst, __gm__ uint32_t* carry, __gm__ uint32_t* src0, __gm__ uint32_t* src1) |
| 160 | { | 176 | { |
| 161 | asc_init(); | 177 | asc_init(); |
| 162 | - __ubuf__ uint32_t dst_local[ELEMENT_COUNT]; | 178 | + __ubuf__ uint32_t dst_local[PADDED_ELEMENT_COUNT]; |
| 163 | - __ubuf__ uint32_t carry_local[CARRY_WORDS]; | 179 | + __ubuf__ uint32_t carry_local[TOTAL_CARRY_WORDS]; |
| 164 | - __ubuf__ uint32_t src0_local[ELEMENT_COUNT]; | 180 | + __ubuf__ uint32_t src0_local[PADDED_ELEMENT_COUNT]; |
| 165 | - __ubuf__ uint32_t src1_local[ELEMENT_COUNT]; | 181 | + __ubuf__ uint32_t src1_local[PADDED_ELEMENT_COUNT]; |
| 166 | - asc_copy_gm2ub_align(src0_local, src0, ELEMENT_COUNT * sizeof(uint32_t)); | 182 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 167 | - asc_copy_gm2ub_align(src1_local, src1, ELEMENT_COUNT * sizeof(uint32_t)); | 183 | + asc_copy_gm2ub_align(src0_local, src0, PADDED_ELEMENT_COUNT * sizeof(uint32_t)); |
| 168 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 184 | + asc_copy_gm2ub_align(src1_local, src1, PADDED_ELEMENT_COUNT * sizeof(uint32_t)); |
| 169 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 185 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 170 | - addc_vf(dst_local, carry_local, src0_local, src1_local); | 186 | + |
| 171 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 187 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint32_t)); |
| 172 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 188 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 173 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(uint32_t)); | 189 | + asc_lock(PIPE_V, MUTEX_ID); |
| 174 | - asc_copy_ub2gm_align(carry, carry_local, CARRY_WORDS * sizeof(uint32_t)); | 190 | + asc_vf_call<addc_vf>(dst_local, carry_local, src0_local, src1_local, one_repeat_size, repeat_time); |
| 191 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 192 | + | ||
| 193 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 194 | + asc_copy_ub2gm_align(dst, dst_local, PADDED_ELEMENT_COUNT * sizeof(uint32_t)); | ||
| 195 | + asc_copy_ub2gm_align(carry, carry_local, TOTAL_CARRY_WORDS * sizeof(uint32_t)); | ||
| 196 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 175 | asc_sync(); | 197 | asc_sync(); |
| 176 | } | 198 | } |
| 177 | 199 | ||
| @@ -179,31 +201,43 @@ __global__ __vector__ void asc_addc_kernel(__gm__ uint32_t* dst, __gm__ uint32_t | |||
| 179 | 201 | ||
| 180 | int main() | 202 | int main() |
| 181 | { | 203 | { |
| 182 | - std::vector<uint32_t> src0(ELEMENT_COUNT); | 204 | + std::vector<uint32_t> src0(PADDED_ELEMENT_COUNT, 0); |
| 183 | - std::vector<uint32_t> src1(ELEMENT_COUNT); | 205 | + std::vector<uint32_t> src1(PADDED_ELEMENT_COUNT, 0); |
| 184 | - std::vector<uint32_t> output(ELEMENT_COUNT, 0); | 206 | + std::vector<uint32_t> output(PADDED_ELEMENT_COUNT, 0); |
| 185 | - std::vector<uint32_t> carry(CARRY_WORDS, 0); | 207 | + std::vector<uint32_t> carry(TOTAL_CARRY_WORDS, 0); |
| 186 | - std::vector<uint32_t> golden(ELEMENT_COUNT, 2); | 208 | + std::vector<uint32_t> golden(PADDED_ELEMENT_COUNT, 0); |
| 187 | - std::vector<uint32_t> golden_carry(CARRY_WORDS, 0x11111111U); | 209 | + std::vector<uint32_t> golden_carry(TOTAL_CARRY_WORDS, 0); |
| 188 | 210 | ||
| 189 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 211 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 190 | src0[i] = std::numeric_limits<uint32_t>::max() - i; | 212 | src0[i] = std::numeric_limits<uint32_t>::max() - i; |
| 191 | src1[i] = i + 2; | 213 | src1[i] = i + 2; |
| 214 | + golden[i] = 2; | ||
| 215 | + } | ||
| 216 | + for (uint32_t repeat = 0; repeat < REPEAT_COUNT; ++repeat) { | ||
| 217 | + const uint32_t valid_count = (TOTAL_LENGTH - repeat * ELEMENTS_PER_REGISTER > ELEMENTS_PER_REGISTER) ? | ||
| 218 | + ELEMENTS_PER_REGISTER : TOTAL_LENGTH - repeat * ELEMENTS_PER_REGISTER; | ||
| 219 | + for (uint32_t i = 0; i < CARRY_WORDS; ++i) { | ||
| 220 | + const uint32_t remain = (valid_count > i * 8) ? valid_count - i * 8 : 0; | ||
| 221 | + const uint32_t lanes = (remain > 8) ? 8 : remain; | ||
| 222 | + uint32_t word = 0; | ||
| 223 | + for (uint32_t lane = 0; lane < lanes; ++lane) word |= 1U << (lane * 4); | ||
| 224 | + golden_carry[repeat * CARRY_WORDS + i] = word; | ||
| 225 | + } | ||
| 192 | } | 226 | } |
| 193 | 227 | ||
| 194 | aclInit(nullptr); | 228 | aclInit(nullptr); |
| 195 | aclrtSetDevice(0); | 229 | aclrtSetDevice(0); |
| 196 | uint32_t* src0_device = nullptr; | 230 | uint32_t* src0_device = nullptr; |
| 197 | - aclrtMalloc(reinterpret_cast<void**>(&src0_device), (ELEMENT_COUNT) * sizeof(uint32_t), | 231 | + aclrtMalloc(reinterpret_cast<void**>(&src0_device), (PADDED_ELEMENT_COUNT) * sizeof(uint32_t), |
| 198 | ACL_MEM_MALLOC_HUGE_FIRST); | 232 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 199 | uint32_t* src1_device = nullptr; | 233 | uint32_t* src1_device = nullptr; |
| 200 | - aclrtMalloc(reinterpret_cast<void**>(&src1_device), (ELEMENT_COUNT) * sizeof(uint32_t), | 234 | + aclrtMalloc(reinterpret_cast<void**>(&src1_device), (PADDED_ELEMENT_COUNT) * sizeof(uint32_t), |
| 201 | ACL_MEM_MALLOC_HUGE_FIRST); | 235 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 202 | uint32_t* dst_device = nullptr; | 236 | uint32_t* dst_device = nullptr; |
| 203 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(uint32_t), | 237 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (PADDED_ELEMENT_COUNT) * sizeof(uint32_t), |
| 204 | ACL_MEM_MALLOC_HUGE_FIRST); | 238 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 205 | uint32_t* carry_device = nullptr; | 239 | uint32_t* carry_device = nullptr; |
| 206 | - aclrtMalloc(reinterpret_cast<void**>(&carry_device), (CARRY_WORDS) * sizeof(uint32_t), | 240 | + aclrtMalloc(reinterpret_cast<void**>(&carry_device), (TOTAL_CARRY_WORDS) * sizeof(uint32_t), |
| 207 | ACL_MEM_MALLOC_HUGE_FIRST); | 241 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 208 | aclrtMemcpy(src0_device, src0.size() * sizeof(uint32_t), src0.data(), src0.size() * sizeof(uint32_t), | 242 | aclrtMemcpy(src0_device, src0.size() * sizeof(uint32_t), src0.data(), src0.size() * sizeof(uint32_t), |
| 209 | ACL_MEMCPY_HOST_TO_DEVICE); | 243 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -223,7 +257,8 @@ int main() | |||
| 223 | print_data("Carry words", carry); | 257 | print_data("Carry words", carry); |
| 224 | print_data("Golden output", golden); | 258 | print_data("Golden output", golden); |
| 225 | print_data("Golden carry words", golden_carry); | 259 | print_data("Golden carry words", golden_carry); |
| 226 | - const bool passed = compare_data(output, golden) && compare_data(carry, golden_carry); | 260 | + bool passed = compare_data(carry, golden_carry); |
| 261 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) passed = passed && output[i] == golden[i]; | ||
| 227 | std::cout << (passed ? "[Success] asc_addc passed." : "[Failed] asc_addc failed.") << std::endl; | 262 | std::cout << (passed ? "[Success] asc_addc passed." : "[Failed] asc_addc failed.") << std::endl; |
| 228 | aclrtFree(dst_device); | 263 | aclrtFree(dst_device); |
| 229 | aclrtFree(carry_device); | 264 | aclrtFree(carry_device); |
| @@ -116,9 +116,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 116 | #include <vector> | 116 | #include <vector> |
| 117 | 117 | ||
| 118 | #include "c_api/asc_simd.h" | 118 | #include "c_api/asc_simd.h" |
| 119 | +#include "utils/std/cmath.h" | ||
| 119 | #include "acl/acl.h" | 120 | #include "acl/acl.h" |
| 120 | 121 | ||
| 121 | namespace { | 122 | namespace { |
| 123 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 124 | + | ||
| 122 | template <typename T> | 125 | template <typename T> |
| 123 | void print_data(const char* label, const std::vector<T>& values) | 126 | void print_data(const char* label, const std::vector<T>& values) |
| 124 | { | 127 | { |
| @@ -141,46 +144,64 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 141 | return true; | 144 | return true; |
| 142 | } | 145 | } |
| 143 | 146 | ||
| 144 | -constexpr uint32_t ELEMENT_COUNT = 64; | 147 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 148 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(float); | ||
| 149 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 150 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(float); | ||
| 151 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 152 | +constexpr uint32_t REPEAT_COUNT = | ||
| 153 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 154 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 155 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 145 | 156 | ||
| 146 | -__simd_vf__ inline void div_vf(__ubuf__ float* dst, __ubuf__ float* src0, __ubuf__ float* src1) | 157 | +__simd_vf__ inline void div_vf(__ubuf__ float* dst, __ubuf__ float* src0, __ubuf__ float* src1, uint32_t one_repeat_size, uint16_t repeat_time) |
| 147 | { | 158 | { |
| 148 | vector_float dst_reg; | 159 | vector_float dst_reg; |
| 149 | vector_float src0_reg; | 160 | vector_float src0_reg; |
| 150 | vector_float src1_reg; | 161 | vector_float src1_reg; |
| 151 | - uint32_t count = ELEMENT_COUNT; | 162 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 152 | - vector_bool mask = asc_update_mask_b32(count); | 163 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 153 | - asc_loadalign(src0_reg, src0); | 164 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 154 | - asc_loadalign(src1_reg, src1); | 165 | + const uint32_t offset = i * one_repeat_size; |
| 155 | - asc_div(dst_reg, src0_reg, src1_reg, mask); | 166 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 156 | - asc_storealign(dst, dst_reg, mask); | 167 | + asc_loadalign(src0_reg, src0 + offset); |
| 168 | + asc_loadalign(src1_reg, src1 + offset); | ||
| 169 | + asc_div(dst_reg, src0_reg, src1_reg, mask); | ||
| 170 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 171 | + } | ||
| 157 | } | 172 | } |
| 158 | 173 | ||
| 159 | __global__ __vector__ void asc_div_kernel(__gm__ float* dst, __gm__ float* src0, __gm__ float* src1) | 174 | __global__ __vector__ void asc_div_kernel(__gm__ float* dst, __gm__ float* src0, __gm__ float* src1) |
| 160 | { | 175 | { |
| 161 | asc_init(); | 176 | asc_init(); |
| 162 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 177 | + __ubuf__ float dst_local[PADDED_ELEMENT_COUNT]; |
| 163 | - __ubuf__ float src0_local[ELEMENT_COUNT]; | 178 | + __ubuf__ float src0_local[PADDED_ELEMENT_COUNT]; |
| 164 | - __ubuf__ float src1_local[ELEMENT_COUNT]; | 179 | + __ubuf__ float src1_local[PADDED_ELEMENT_COUNT]; |
| 165 | - asc_copy_gm2ub_align(src0_local, src0, ELEMENT_COUNT * sizeof(float)); | 180 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 166 | - asc_copy_gm2ub_align(src1_local, src1, ELEMENT_COUNT * sizeof(float)); | 181 | + asc_copy_gm2ub_align(src0_local, src0, TOTAL_LENGTH * sizeof(float)); |
| 167 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 182 | + asc_copy_gm2ub_align(src1_local, src1, TOTAL_LENGTH * sizeof(float)); |
| 168 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 183 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 169 | - div_vf(dst_local, src0_local, src1_local); | 184 | + |
| 170 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 185 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(float)); |
| 171 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 186 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 172 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 187 | + asc_lock(PIPE_V, MUTEX_ID); |
| 188 | + asc_vf_call<div_vf>(dst_local, src0_local, src1_local, one_repeat_size, repeat_time); | ||
| 189 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 190 | + | ||
| 191 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 192 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(float)); | ||
| 193 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 173 | asc_sync(); | 194 | asc_sync(); |
| 174 | } | 195 | } |
| 175 | } // namespace | 196 | } // namespace |
| 176 | 197 | ||
| 177 | int main() | 198 | int main() |
| 178 | { | 199 | { |
| 179 | - std::vector<float> src0(ELEMENT_COUNT); | 200 | + std::vector<float> src0(TOTAL_LENGTH); |
| 180 | - std::vector<float> src1(ELEMENT_COUNT); | 201 | + std::vector<float> src1(TOTAL_LENGTH); |
| 181 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 202 | + std::vector<float> output(TOTAL_LENGTH, 0.0f); |
| 182 | - std::vector<float> golden(ELEMENT_COUNT); | 203 | + std::vector<float> golden(TOTAL_LENGTH); |
| 183 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 204 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 184 | src0[i] = static_cast<float>(i + 1); | 205 | src0[i] = static_cast<float>(i + 1); |
| 185 | src1[i] = static_cast<float>(i % 8 + 1); | 206 | src1[i] = static_cast<float>(i % 8 + 1); |
| 186 | golden[i] = src0[i] / src1[i]; | 207 | golden[i] = src0[i] / src1[i]; |
| @@ -189,13 +210,13 @@ int main() | |||
| 189 | aclInit(nullptr); | 210 | aclInit(nullptr); |
| 190 | aclrtSetDevice(0); | 211 | aclrtSetDevice(0); |
| 191 | float* src0_device = nullptr; | 212 | float* src0_device = nullptr; |
| 192 | - aclrtMalloc(reinterpret_cast<void**>(&src0_device), (ELEMENT_COUNT) * sizeof(float), | 213 | + aclrtMalloc(reinterpret_cast<void**>(&src0_device), (TOTAL_LENGTH) * sizeof(float), |
| 193 | ACL_MEM_MALLOC_HUGE_FIRST); | 214 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 194 | float* src1_device = nullptr; | 215 | float* src1_device = nullptr; |
| 195 | - aclrtMalloc(reinterpret_cast<void**>(&src1_device), (ELEMENT_COUNT) * sizeof(float), | 216 | + aclrtMalloc(reinterpret_cast<void**>(&src1_device), (TOTAL_LENGTH) * sizeof(float), |
| 196 | ACL_MEM_MALLOC_HUGE_FIRST); | 217 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 197 | float* dst_device = nullptr; | 218 | float* dst_device = nullptr; |
| 198 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 219 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(float), |
| 199 | ACL_MEM_MALLOC_HUGE_FIRST); | 220 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 200 | aclrtMemcpy(src0_device, src0.size() * sizeof(float), src0.data(), src0.size() * sizeof(float), | 221 | aclrtMemcpy(src0_device, src0.size() * sizeof(float), src0.data(), src0.size() * sizeof(float), |
| 201 | ACL_MEMCPY_HOST_TO_DEVICE); | 222 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -98,6 +98,8 @@ __simd_callee__ inline vector_float asc_exp(vector_float src, | |||
| 98 | ```bash | 98 | ```bash |
| 99 | bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main | 99 | bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main |
| 100 | ``` | 100 | ``` |
| 101 | + | ||
| 102 | +**注意:** 本示例主机侧golden计算会调用需由libm提供的数学函数:`std::exp`,编译命令需要保留`-lm`以链接数学库。 | ||
| 101 | <!-- end id8 --> | 103 | <!-- end id8 --> |
| 102 | 104 | ||
| 103 | ```c | 105 | ```c |
| @@ -108,9 +110,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main | |||
| 108 | #include <vector> | 110 | #include <vector> |
| 109 | 111 | ||
| 110 | #include "c_api/asc_simd.h" | 112 | #include "c_api/asc_simd.h" |
| 113 | +#include "utils/std/cmath.h" | ||
| 111 | #include "acl/acl.h" | 114 | #include "acl/acl.h" |
| 112 | 115 | ||
| 113 | namespace { | 116 | namespace { |
| 117 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 118 | + | ||
| 114 | template <typename T> | 119 | template <typename T> |
| 115 | void print_data(const char* label, const std::vector<T>& values) | 120 | void print_data(const char* label, const std::vector<T>& values) |
| 116 | { | 121 | { |
| @@ -133,41 +138,59 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 133 | return true; | 138 | return true; |
| 134 | } | 139 | } |
| 135 | 140 | ||
| 136 | -constexpr uint32_t ELEMENT_COUNT = 64; | 141 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 142 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(float); | ||
| 143 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 144 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(float); | ||
| 145 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 146 | +constexpr uint32_t REPEAT_COUNT = | ||
| 147 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 148 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 149 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 137 | 150 | ||
| 138 | -__simd_vf__ inline void exp_vf(__ubuf__ float* dst, __ubuf__ float* src) | 151 | +__simd_vf__ inline void exp_vf(__ubuf__ float* dst, __ubuf__ float* src, uint32_t one_repeat_size, uint16_t repeat_time) |
| 139 | { | 152 | { |
| 140 | vector_float dst_reg; | 153 | vector_float dst_reg; |
| 141 | vector_float src_reg; | 154 | vector_float src_reg; |
| 142 | - uint32_t count = ELEMENT_COUNT; | 155 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 143 | - vector_bool mask = asc_update_mask_b32(count); | 156 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 144 | - asc_loadalign(src_reg, src); | 157 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 145 | - asc_exp(dst_reg, src_reg, mask); | 158 | + const uint32_t offset = i * one_repeat_size; |
| 146 | - asc_storealign(dst, dst_reg, mask); | 159 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 160 | + asc_loadalign(src_reg, src + offset); | ||
| 161 | + asc_exp(dst_reg, src_reg, mask); | ||
| 162 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 163 | + } | ||
| 147 | } | 164 | } |
| 148 | 165 | ||
| 149 | __global__ __vector__ void asc_exp_kernel(__gm__ float* dst, __gm__ float* src) | 166 | __global__ __vector__ void asc_exp_kernel(__gm__ float* dst, __gm__ float* src) |
| 150 | { | 167 | { |
| 151 | asc_init(); | 168 | asc_init(); |
| 152 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 169 | + __ubuf__ float dst_local[PADDED_ELEMENT_COUNT]; |
| 153 | - __ubuf__ float src_local[ELEMENT_COUNT]; | 170 | + __ubuf__ float src_local[PADDED_ELEMENT_COUNT]; |
| 154 | - asc_copy_gm2ub_align(src_local, src, ELEMENT_COUNT * sizeof(float)); | 171 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 155 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 172 | + asc_copy_gm2ub_align(src_local, src, TOTAL_LENGTH * sizeof(float)); |
| 156 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 173 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 157 | - exp_vf(dst_local, src_local); | 174 | + |
| 158 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 175 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(float)); |
| 159 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 176 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 160 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 177 | + asc_lock(PIPE_V, MUTEX_ID); |
| 178 | + asc_vf_call<exp_vf>(dst_local, src_local, one_repeat_size, repeat_time); | ||
| 179 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 180 | + | ||
| 181 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 182 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(float)); | ||
| 183 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 161 | asc_sync(); | 184 | asc_sync(); |
| 162 | } | 185 | } |
| 163 | } // namespace | 186 | } // namespace |
| 164 | 187 | ||
| 165 | int main() | 188 | int main() |
| 166 | { | 189 | { |
| 167 | - std::vector<float> src(ELEMENT_COUNT); | 190 | + std::vector<float> src(TOTAL_LENGTH); |
| 168 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 191 | + std::vector<float> output(TOTAL_LENGTH, 0.0f); |
| 169 | - std::vector<float> golden(ELEMENT_COUNT); | 192 | + std::vector<float> golden(TOTAL_LENGTH); |
| 170 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 193 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 171 | src[i] = (static_cast<int>(i % 5) - 2) * 0.25f; | 194 | src[i] = (static_cast<int>(i % 5) - 2) * 0.25f; |
| 172 | golden[i] = std::exp(src[i]); | 195 | golden[i] = std::exp(src[i]); |
| 173 | } | 196 | } |
| @@ -175,10 +198,10 @@ int main() | |||
| 175 | aclInit(nullptr); | 198 | aclInit(nullptr); |
| 176 | aclrtSetDevice(0); | 199 | aclrtSetDevice(0); |
| 177 | float* src_device = nullptr; | 200 | float* src_device = nullptr; |
| 178 | - aclrtMalloc(reinterpret_cast<void**>(&src_device), (ELEMENT_COUNT) * sizeof(float), | 201 | + aclrtMalloc(reinterpret_cast<void**>(&src_device), (TOTAL_LENGTH) * sizeof(float), |
| 179 | ACL_MEM_MALLOC_HUGE_FIRST); | 202 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 180 | float* dst_device = nullptr; | 203 | float* dst_device = nullptr; |
| 181 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 204 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(float), |
| 182 | ACL_MEM_MALLOC_HUGE_FIRST); | 205 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 183 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), | 206 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), |
| 184 | ACL_MEMCPY_HOST_TO_DEVICE); | 207 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -89,6 +89,8 @@ __simd_callee__ inline void asc_ln(vector_half& dst, | |||
| 89 | ```bash | 89 | ```bash |
| 90 | bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main | 90 | bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main |
| 91 | ``` | 91 | ``` |
| 92 | + | ||
| 93 | +**注意:** 本示例主机侧golden计算会调用需由libm提供的数学函数:`std::log`,编译命令需要保留`-lm`以链接数学库。 | ||
| 92 | <!-- end id8 --> | 94 | <!-- end id8 --> |
| 93 | 95 | ||
| 94 | ```cpp | 96 | ```cpp |
| @@ -99,9 +101,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main | |||
| 99 | #include <vector> | 101 | #include <vector> |
| 100 | 102 | ||
| 101 | #include "c_api/asc_simd.h" | 103 | #include "c_api/asc_simd.h" |
| 104 | +#include "utils/std/cmath.h" | ||
| 102 | #include "acl/acl.h" | 105 | #include "acl/acl.h" |
| 103 | 106 | ||
| 104 | namespace { | 107 | namespace { |
| 108 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 109 | + | ||
| 105 | template <typename T> | 110 | template <typename T> |
| 106 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) | 111 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) |
| 107 | { | 112 | { |
| @@ -114,31 +119,49 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 114 | return true; | 119 | return true; |
| 115 | } | 120 | } |
| 116 | 121 | ||
| 117 | -constexpr uint32_t ELEMENT_COUNT = 64; | 122 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 123 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(float); | ||
| 124 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 125 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(float); | ||
| 126 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 127 | +constexpr uint32_t REPEAT_COUNT = | ||
| 128 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 129 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 130 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 118 | 131 | ||
| 119 | -__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src) | 132 | +__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src, uint32_t one_repeat_size, uint16_t repeat_time) |
| 120 | { | 133 | { |
| 121 | vector_float dst_reg; | 134 | vector_float dst_reg; |
| 122 | vector_float src_reg; | 135 | vector_float src_reg; |
| 123 | - uint32_t count = ELEMENT_COUNT; | 136 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 124 | - vector_bool mask = asc_update_mask_b32(count); | 137 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 125 | - asc_loadalign(src_reg, src); | 138 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 126 | - asc_ln(dst_reg, src_reg, mask); | 139 | + const uint32_t offset = i * one_repeat_size; |
| 127 | - asc_storealign(dst, dst_reg, mask); | 140 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 141 | + asc_loadalign(src_reg, src + offset); | ||
| 142 | + asc_ln(dst_reg, src_reg, mask); | ||
| 143 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 144 | + } | ||
| 128 | } | 145 | } |
| 129 | 146 | ||
| 130 | __global__ __vector__ void asc_ln_kernel(__gm__ float* dst, __gm__ float* src) | 147 | __global__ __vector__ void asc_ln_kernel(__gm__ float* dst, __gm__ float* src) |
| 131 | { | 148 | { |
| 132 | asc_init(); | 149 | asc_init(); |
| 133 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 150 | + __ubuf__ float dst_local[PADDED_ELEMENT_COUNT]; |
| 134 | - __ubuf__ float src_local[ELEMENT_COUNT]; | 151 | + __ubuf__ float src_local[PADDED_ELEMENT_COUNT]; |
| 135 | - asc_copy_gm2ub_align(src_local, src, ELEMENT_COUNT * sizeof(float)); | 152 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 136 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 153 | + asc_copy_gm2ub_align(src_local, src, TOTAL_LENGTH * sizeof(float)); |
| 137 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 154 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 138 | - compute(dst_local, src_local); | 155 | + |
| 139 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 156 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(float)); |
| 140 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 157 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 141 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 158 | + asc_lock(PIPE_V, MUTEX_ID); |
| 159 | + asc_vf_call<compute>(dst_local, src_local, one_repeat_size, repeat_time); | ||
| 160 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 161 | + | ||
| 162 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 163 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(float)); | ||
| 164 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 142 | asc_sync(); | 165 | asc_sync(); |
| 143 | } | 166 | } |
| 144 | 167 | ||
| @@ -146,10 +169,10 @@ __global__ __vector__ void asc_ln_kernel(__gm__ float* dst, __gm__ float* src) | |||
| 146 | 169 | ||
| 147 | int main() | 170 | int main() |
| 148 | { | 171 | { |
| 149 | - std::vector<float> src(ELEMENT_COUNT); | 172 | + std::vector<float> src(TOTAL_LENGTH); |
| 150 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 173 | + std::vector<float> output(TOTAL_LENGTH, 0.0f); |
| 151 | - std::vector<float> golden(ELEMENT_COUNT); | 174 | + std::vector<float> golden(TOTAL_LENGTH); |
| 152 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 175 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 153 | src[i] = 0.5f + static_cast<float>(i % 8) * 0.25f; | 176 | src[i] = 0.5f + static_cast<float>(i % 8) * 0.25f; |
| 154 | golden[i] = std::log(src[i]); | 177 | golden[i] = std::log(src[i]); |
| 155 | } | 178 | } |
| @@ -157,10 +180,10 @@ int main() | |||
| 157 | aclInit(nullptr); | 180 | aclInit(nullptr); |
| 158 | aclrtSetDevice(0); | 181 | aclrtSetDevice(0); |
| 159 | float* src_device = nullptr; | 182 | float* src_device = nullptr; |
| 160 | - aclrtMalloc(reinterpret_cast<void**>(&src_device), (ELEMENT_COUNT) * sizeof(float), | 183 | + aclrtMalloc(reinterpret_cast<void**>(&src_device), (TOTAL_LENGTH) * sizeof(float), |
| 161 | ACL_MEM_MALLOC_HUGE_FIRST); | 184 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 162 | float* dst_device = nullptr; | 185 | float* dst_device = nullptr; |
| 163 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 186 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(float), |
| 164 | ACL_MEM_MALLOC_HUGE_FIRST); | 187 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 165 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), | 188 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), |
| 166 | ACL_MEMCPY_HOST_TO_DEVICE); | 189 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -90,6 +90,8 @@ __simd_callee__ inline void asc_log(vector_half& dst, | |||
| 90 | ```bash | 90 | ```bash |
| 91 | bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main | 91 | bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main |
| 92 | ``` | 92 | ``` |
| 93 | + | ||
| 94 | +**注意:** 本示例主机侧golden计算会调用需由libm提供的数学函数:`std::log`,编译命令需要保留`-lm`以链接数学库。 | ||
| 93 | <!-- end id8 --> | 95 | <!-- end id8 --> |
| 94 | 96 | ||
| 95 | ```cpp | 97 | ```cpp |
| @@ -100,9 +102,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main | |||
| 100 | #include <vector> | 102 | #include <vector> |
| 101 | 103 | ||
| 102 | #include "c_api/asc_simd.h" | 104 | #include "c_api/asc_simd.h" |
| 105 | +#include "utils/std/cmath.h" | ||
| 103 | #include "acl/acl.h" | 106 | #include "acl/acl.h" |
| 104 | 107 | ||
| 105 | namespace { | 108 | namespace { |
| 109 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 110 | + | ||
| 106 | template <typename T> | 111 | template <typename T> |
| 107 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) | 112 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) |
| 108 | { | 113 | { |
| @@ -115,31 +120,49 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 115 | return true; | 120 | return true; |
| 116 | } | 121 | } |
| 117 | 122 | ||
| 118 | -constexpr uint32_t ELEMENT_COUNT = 64; | 123 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 124 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(float); | ||
| 125 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 126 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(float); | ||
| 127 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 128 | +constexpr uint32_t REPEAT_COUNT = | ||
| 129 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 130 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 131 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 119 | 132 | ||
| 120 | -__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src) | 133 | +__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src, uint32_t one_repeat_size, uint16_t repeat_time) |
| 121 | { | 134 | { |
| 122 | vector_float dst_reg; | 135 | vector_float dst_reg; |
| 123 | vector_float src_reg; | 136 | vector_float src_reg; |
| 124 | - uint32_t count = ELEMENT_COUNT; | 137 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 125 | - vector_bool mask = asc_update_mask_b32(count); | 138 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 126 | - asc_loadalign(src_reg, src); | 139 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 127 | - asc_log(dst_reg, src_reg, mask); | 140 | + const uint32_t offset = i * one_repeat_size; |
| 128 | - asc_storealign(dst, dst_reg, mask); | 141 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 142 | + asc_loadalign(src_reg, src + offset); | ||
| 143 | + asc_log(dst_reg, src_reg, mask); | ||
| 144 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 145 | + } | ||
| 129 | } | 146 | } |
| 130 | 147 | ||
| 131 | __global__ __vector__ void asc_log_kernel(__gm__ float* dst, __gm__ float* src) | 148 | __global__ __vector__ void asc_log_kernel(__gm__ float* dst, __gm__ float* src) |
| 132 | { | 149 | { |
| 133 | asc_init(); | 150 | asc_init(); |
| 134 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 151 | + __ubuf__ float dst_local[PADDED_ELEMENT_COUNT]; |
| 135 | - __ubuf__ float src_local[ELEMENT_COUNT]; | 152 | + __ubuf__ float src_local[PADDED_ELEMENT_COUNT]; |
| 136 | - asc_copy_gm2ub_align(src_local, src, ELEMENT_COUNT * sizeof(float)); | 153 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 137 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 154 | + asc_copy_gm2ub_align(src_local, src, TOTAL_LENGTH * sizeof(float)); |
| 138 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 155 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 139 | - compute(dst_local, src_local); | 156 | + |
| 140 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 157 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(float)); |
| 141 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 158 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 142 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 159 | + asc_lock(PIPE_V, MUTEX_ID); |
| 160 | + asc_vf_call<compute>(dst_local, src_local, one_repeat_size, repeat_time); | ||
| 161 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 162 | + | ||
| 163 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 164 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(float)); | ||
| 165 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 143 | asc_sync(); | 166 | asc_sync(); |
| 144 | } | 167 | } |
| 145 | 168 | ||
| @@ -147,10 +170,10 @@ __global__ __vector__ void asc_log_kernel(__gm__ float* dst, __gm__ float* src) | |||
| 147 | 170 | ||
| 148 | int main() | 171 | int main() |
| 149 | { | 172 | { |
| 150 | - std::vector<float> src(ELEMENT_COUNT); | 173 | + std::vector<float> src(TOTAL_LENGTH); |
| 151 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 174 | + std::vector<float> output(TOTAL_LENGTH, 0.0f); |
| 152 | - std::vector<float> golden(ELEMENT_COUNT); | 175 | + std::vector<float> golden(TOTAL_LENGTH); |
| 153 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 176 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 154 | src[i] = 0.5f + static_cast<float>(i % 8) * 0.25f; | 177 | src[i] = 0.5f + static_cast<float>(i % 8) * 0.25f; |
| 155 | golden[i] = std::log(src[i]); | 178 | golden[i] = std::log(src[i]); |
| 156 | } | 179 | } |
| @@ -158,10 +181,10 @@ int main() | |||
| 158 | aclInit(nullptr); | 181 | aclInit(nullptr); |
| 159 | aclrtSetDevice(0); | 182 | aclrtSetDevice(0); |
| 160 | float* src_device = nullptr; | 183 | float* src_device = nullptr; |
| 161 | - aclrtMalloc(reinterpret_cast<void**>(&src_device), (ELEMENT_COUNT) * sizeof(float), | 184 | + aclrtMalloc(reinterpret_cast<void**>(&src_device), (TOTAL_LENGTH) * sizeof(float), |
| 162 | ACL_MEM_MALLOC_HUGE_FIRST); | 185 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 163 | float* dst_device = nullptr; | 186 | float* dst_device = nullptr; |
| 164 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 187 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(float), |
| 165 | ACL_MEM_MALLOC_HUGE_FIRST); | 188 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 166 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), | 189 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), |
| 167 | ACL_MEMCPY_HOST_TO_DEVICE); | 190 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -115,9 +115,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 115 | #include <vector> | 115 | #include <vector> |
| 116 | 116 | ||
| 117 | #include "c_api/asc_simd.h" | 117 | #include "c_api/asc_simd.h" |
| 118 | +#include "utils/std/cmath.h" | ||
| 118 | #include "acl/acl.h" | 119 | #include "acl/acl.h" |
| 119 | 120 | ||
| 120 | namespace { | 121 | namespace { |
| 122 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 123 | + | ||
| 121 | template <typename T> | 124 | template <typename T> |
| 122 | void print_data(const char* label, const std::vector<T>& values) | 125 | void print_data(const char* label, const std::vector<T>& values) |
| 123 | { | 126 | { |
| @@ -140,35 +143,58 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 140 | return true; | 143 | return true; |
| 141 | } | 144 | } |
| 142 | 145 | ||
| 143 | -constexpr uint32_t ELEMENT_COUNT = 64; | 146 | +// 本示例按256字节的寄存器宽度预留UB空间,每个寄存器可容纳256 / sizeof(int32_t) = 64个元素。 |
| 147 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; | ||
| 148 | +// 选取137个有效元素,覆盖两个完整寄存器和一个仅含9个有效元素的尾块。 | ||
| 149 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(int32_t); | ||
| 150 | +// 将字节数换算为元素数,供循环次数和有效元素掩码计算使用。 | ||
| 151 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(int32_t); | ||
| 152 | +// 向上取整得到3个寄存器块;直接整除只得到2,会漏掉尾块。 | ||
| 153 | +constexpr uint32_t REPEAT_COUNT = | ||
| 154 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 155 | +// UB容量扩展为3 * 64 = 192个元素,保证尾轮整寄存器加载时不越过已分配空间。 | ||
| 156 | +// 额外空间仅用于安全加载,计算和写回的有效范围仍由掩码及TOTAL_LENGTH控制。 | ||
| 157 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 144 | 158 | ||
| 145 | -__simd_vf__ inline void max_vf(__ubuf__ float* dst, __ubuf__ float* src0, __ubuf__ float* src1) | 159 | +__simd_vf__ inline void max_vf(__ubuf__ int32_t* dst, __ubuf__ int32_t* src0, __ubuf__ int32_t* src1, uint32_t one_repeat_size, uint16_t repeat_time) |
| 146 | { | 160 | { |
| 147 | - vector_float dst_reg; | 161 | + vector_int32_t dst_reg; |
| 148 | - vector_float src0_reg; | 162 | + vector_int32_t src0_reg; |
| 149 | - vector_float src1_reg; | 163 | + vector_int32_t src1_reg; |
| 150 | - uint32_t count = ELEMENT_COUNT; | 164 | + // 记录尚未处理的有效元素数,由asc_update_mask_b32逐轮扣减。 |
| 151 | - vector_bool mask = asc_update_mask_b32(count); | 165 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 152 | - asc_loadalign(src0_reg, src0); | 166 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 153 | - asc_loadalign(src1_reg, src1); | 167 | + const uint32_t offset = i * one_repeat_size; |
| 154 | - asc_max(dst_reg, src0_reg, src1_reg, mask); | 168 | + // 三轮分别处理64、64、9个元素;尾轮只计算并存储前9个有效元素。 |
| 155 | - asc_storealign(dst, dst_reg, mask); | 169 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 170 | + asc_loadalign(src0_reg, src0 + offset); | ||
| 171 | + asc_loadalign(src1_reg, src1 + offset); | ||
| 172 | + asc_max(dst_reg, src0_reg, src1_reg, mask); | ||
| 173 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 174 | + } | ||
| 156 | } | 175 | } |
| 157 | 176 | ||
| 158 | -__global__ __vector__ void asc_max_kernel(__gm__ float* dst, __gm__ float* src0, __gm__ float* src1) | 177 | +__global__ __vector__ void asc_max_kernel(__gm__ int32_t* dst, __gm__ int32_t* src0, __gm__ int32_t* src1) |
| 159 | { | 178 | { |
| 160 | asc_init(); | 179 | asc_init(); |
| 161 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 180 | + __ubuf__ int32_t dst_local[PADDED_ELEMENT_COUNT]; |
| 162 | - __ubuf__ float src0_local[ELEMENT_COUNT]; | 181 | + __ubuf__ int32_t src0_local[PADDED_ELEMENT_COUNT]; |
| 163 | - __ubuf__ float src1_local[ELEMENT_COUNT]; | 182 | + __ubuf__ int32_t src1_local[PADDED_ELEMENT_COUNT]; |
| 164 | - asc_copy_gm2ub_align(src0_local, src0, ELEMENT_COUNT * sizeof(float)); | 183 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 165 | - asc_copy_gm2ub_align(src1_local, src1, ELEMENT_COUNT * sizeof(float)); | 184 | + asc_copy_gm2ub_align(src0_local, src0, TOTAL_LENGTH * sizeof(int32_t)); |
| 166 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 185 | + asc_copy_gm2ub_align(src1_local, src1, TOTAL_LENGTH * sizeof(int32_t)); |
| 167 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 186 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 168 | - max_vf(dst_local, src0_local, src1_local); | 187 | + |
| 169 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 188 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(int32_t)); |
| 170 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 189 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 171 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 190 | + asc_lock(PIPE_V, MUTEX_ID); |
| 191 | + asc_vf_call<max_vf>(dst_local, src0_local, src1_local, one_repeat_size, repeat_time); | ||
| 192 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 193 | + | ||
| 194 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 195 | + // 只搬出137个有效元素,不把UB中为整寄存器加载预留的填充空间写入GM。 | ||
| 196 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(int32_t)); | ||
| 197 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 172 | asc_sync(); | 198 | asc_sync(); |
| 173 | } | 199 | } |
| 174 | 200 | ||
| @@ -176,42 +202,42 @@ __global__ __vector__ void asc_max_kernel(__gm__ float* dst, __gm__ float* src0, | |||
| 176 | 202 | ||
| 177 | int main() | 203 | int main() |
| 178 | { | 204 | { |
| 179 | - std::vector<float> src0(ELEMENT_COUNT); | 205 | + std::vector<int32_t> src0(TOTAL_LENGTH); |
| 180 | - std::vector<float> src1(ELEMENT_COUNT); | 206 | + std::vector<int32_t> src1(TOTAL_LENGTH); |
| 181 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 207 | + std::vector<int32_t> output(TOTAL_LENGTH, 0); |
| 182 | - std::vector<float> golden(ELEMENT_COUNT); | 208 | + std::vector<int32_t> golden(TOTAL_LENGTH); |
| 183 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 209 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 184 | - src0[i] = static_cast<float>(i) - 24.0f; | 210 | + src0[i] = static_cast<int32_t>(i) - 64; |
| 185 | - src1[i] = 16.0f - static_cast<float>(i) * 0.5f; | 211 | + src1[i] = 32 - static_cast<int32_t>(i); |
| 186 | - golden[i] = std::max(src0[i], src1[i]); | 212 | + golden[i] = src0[i] > src1[i] ? src0[i] : src1[i]; |
| 187 | } | 213 | } |
| 188 | 214 | ||
| 189 | aclInit(nullptr); | 215 | aclInit(nullptr); |
| 190 | aclrtSetDevice(0); | 216 | aclrtSetDevice(0); |
| 191 | - float* src0_device = nullptr; | 217 | + int32_t* src0_device = nullptr; |
| 192 | - aclrtMalloc(reinterpret_cast<void**>(&src0_device), (ELEMENT_COUNT) * sizeof(float), | 218 | + aclrtMalloc(reinterpret_cast<void**>(&src0_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 193 | ACL_MEM_MALLOC_HUGE_FIRST); | 219 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 194 | - float* src1_device = nullptr; | 220 | + int32_t* src1_device = nullptr; |
| 195 | - aclrtMalloc(reinterpret_cast<void**>(&src1_device), (ELEMENT_COUNT) * sizeof(float), | 221 | + aclrtMalloc(reinterpret_cast<void**>(&src1_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 196 | ACL_MEM_MALLOC_HUGE_FIRST); | 222 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 197 | - float* dst_device = nullptr; | 223 | + int32_t* dst_device = nullptr; |
| 198 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 224 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 199 | ACL_MEM_MALLOC_HUGE_FIRST); | 225 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 200 | - aclrtMemcpy(src0_device, src0.size() * sizeof(float), src0.data(), src0.size() * sizeof(float), | 226 | + aclrtMemcpy(src0_device, src0.size() * sizeof(int32_t), src0.data(), src0.size() * sizeof(int32_t), |
| 201 | ACL_MEMCPY_HOST_TO_DEVICE); | 227 | ACL_MEMCPY_HOST_TO_DEVICE); |
| 202 | - aclrtMemcpy(src1_device, src1.size() * sizeof(float), src1.data(), src1.size() * sizeof(float), | 228 | + aclrtMemcpy(src1_device, src1.size() * sizeof(int32_t), src1.data(), src1.size() * sizeof(int32_t), |
| 203 | ACL_MEMCPY_HOST_TO_DEVICE); | 229 | ACL_MEMCPY_HOST_TO_DEVICE); |
| 204 | 230 | ||
| 205 | asc_max_kernel<<<1, 0>>>(dst_device, src0_device, src1_device); | 231 | asc_max_kernel<<<1, 0>>>(dst_device, src0_device, src1_device); |
| 206 | aclrtSynchronizeDevice(); | 232 | aclrtSynchronizeDevice(); |
| 207 | - aclrtMemcpy(output.data(), output.size() * sizeof(float), dst_device, output.size() * sizeof(float), | 233 | + aclrtMemcpy(output.data(), output.size() * sizeof(int32_t), dst_device, output.size() * sizeof(int32_t), |
| 208 | ACL_MEMCPY_DEVICE_TO_HOST); | 234 | ACL_MEMCPY_DEVICE_TO_HOST); |
| 209 | 235 | ||
| 210 | print_data("Input src0", src0); | 236 | print_data("Input src0", src0); |
| 211 | print_data("Input src1", src1); | 237 | print_data("Input src1", src1); |
| 212 | print_data("Output", output); | 238 | print_data("Output", output); |
| 213 | print_data("Golden", golden); | 239 | print_data("Golden", golden); |
| 214 | - const bool passed = compare_data(output, golden, 1e-6); | 240 | + const bool passed = compare_data(output, golden); |
| 215 | std::cout << (passed ? "[Success] asc_max passed." : "[Failed] asc_max failed.") << std::endl; | 241 | std::cout << (passed ? "[Success] asc_max passed." : "[Failed] asc_max failed.") << std::endl; |
| 216 | aclrtFree(dst_device); | 242 | aclrtFree(dst_device); |
| 217 | aclrtFree(src0_device); | 243 | aclrtFree(src0_device); |
| @@ -110,9 +110,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 110 | #include <vector> | 110 | #include <vector> |
| 111 | 111 | ||
| 112 | #include "c_api/asc_simd.h" | 112 | #include "c_api/asc_simd.h" |
| 113 | +#include "utils/std/cmath.h" | ||
| 113 | #include "acl/acl.h" | 114 | #include "acl/acl.h" |
| 114 | 115 | ||
| 115 | namespace { | 116 | namespace { |
| 117 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 118 | + | ||
| 116 | template <typename T> | 119 | template <typename T> |
| 117 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) | 120 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) |
| 118 | { | 121 | { |
| @@ -125,32 +128,50 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 125 | return true; | 128 | return true; |
| 126 | } | 129 | } |
| 127 | 130 | ||
| 128 | -constexpr uint32_t ELEMENT_COUNT = 64; | 131 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 132 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(float); | ||
| 133 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 134 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(float); | ||
| 135 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 136 | +constexpr uint32_t REPEAT_COUNT = | ||
| 137 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 138 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 139 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 129 | constexpr float SCALAR_VALUE = 3.0f; | 140 | constexpr float SCALAR_VALUE = 3.0f; |
| 130 | 141 | ||
| 131 | -__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src) | 142 | +__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src, uint32_t one_repeat_size, uint16_t repeat_time) |
| 132 | { | 143 | { |
| 133 | vector_float dst_reg; | 144 | vector_float dst_reg; |
| 134 | vector_float src_reg; | 145 | vector_float src_reg; |
| 135 | - uint32_t count = ELEMENT_COUNT; | 146 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 136 | - vector_bool mask = asc_update_mask_b32(count); | 147 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 137 | - asc_loadalign(src_reg, src); | 148 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 138 | - asc_max_scalar(dst_reg, src_reg, SCALAR_VALUE, mask); | 149 | + const uint32_t offset = i * one_repeat_size; |
| 139 | - asc_storealign(dst, dst_reg, mask); | 150 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 151 | + asc_loadalign(src_reg, src + offset); | ||
| 152 | + asc_max_scalar(dst_reg, src_reg, SCALAR_VALUE, mask); | ||
| 153 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 154 | + } | ||
| 140 | } | 155 | } |
| 141 | 156 | ||
| 142 | __global__ __vector__ void asc_max_scalar_kernel(__gm__ float* dst, __gm__ float* src) | 157 | __global__ __vector__ void asc_max_scalar_kernel(__gm__ float* dst, __gm__ float* src) |
| 143 | { | 158 | { |
| 144 | asc_init(); | 159 | asc_init(); |
| 145 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 160 | + __ubuf__ float dst_local[PADDED_ELEMENT_COUNT]; |
| 146 | - __ubuf__ float src_local[ELEMENT_COUNT]; | 161 | + __ubuf__ float src_local[PADDED_ELEMENT_COUNT]; |
| 147 | - asc_copy_gm2ub_align(src_local, src, ELEMENT_COUNT * sizeof(float)); | 162 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 148 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 163 | + asc_copy_gm2ub_align(src_local, src, TOTAL_LENGTH * sizeof(float)); |
| 149 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 164 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 150 | - compute(dst_local, src_local); | 165 | + |
| 151 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 166 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(float)); |
| 152 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 167 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 153 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 168 | + asc_lock(PIPE_V, MUTEX_ID); |
| 169 | + asc_vf_call<compute>(dst_local, src_local, one_repeat_size, repeat_time); | ||
| 170 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 171 | + | ||
| 172 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 173 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(float)); | ||
| 174 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 154 | asc_sync(); | 175 | asc_sync(); |
| 155 | } | 176 | } |
| 156 | 177 | ||
| @@ -158,10 +179,10 @@ __global__ __vector__ void asc_max_scalar_kernel(__gm__ float* dst, __gm__ float | |||
| 158 | 179 | ||
| 159 | int main() | 180 | int main() |
| 160 | { | 181 | { |
| 161 | - std::vector<float> src(ELEMENT_COUNT); | 182 | + std::vector<float> src(TOTAL_LENGTH); |
| 162 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 183 | + std::vector<float> output(TOTAL_LENGTH, 0.0f); |
| 163 | - std::vector<float> golden(ELEMENT_COUNT); | 184 | + std::vector<float> golden(TOTAL_LENGTH); |
| 164 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 185 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 165 | src[i] = static_cast<float>(i) - 24.0f; | 186 | src[i] = static_cast<float>(i) - 24.0f; |
| 166 | golden[i] = std::max(src[i], SCALAR_VALUE); | 187 | golden[i] = std::max(src[i], SCALAR_VALUE); |
| 167 | } | 188 | } |
| @@ -169,10 +190,10 @@ int main() | |||
| 169 | aclInit(nullptr); | 190 | aclInit(nullptr); |
| 170 | aclrtSetDevice(0); | 191 | aclrtSetDevice(0); |
| 171 | float* src_device = nullptr; | 192 | float* src_device = nullptr; |
| 172 | - aclrtMalloc(reinterpret_cast<void**>(&src_device), (ELEMENT_COUNT) * sizeof(float), | 193 | + aclrtMalloc(reinterpret_cast<void**>(&src_device), (TOTAL_LENGTH) * sizeof(float), |
| 173 | ACL_MEM_MALLOC_HUGE_FIRST); | 194 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 174 | float* dst_device = nullptr; | 195 | float* dst_device = nullptr; |
| 175 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 196 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(float), |
| 176 | ACL_MEM_MALLOC_HUGE_FIRST); | 197 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 177 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), | 198 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), |
| 178 | ACL_MEMCPY_HOST_TO_DEVICE); | 199 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -114,9 +114,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 114 | #include <vector> | 114 | #include <vector> |
| 115 | 115 | ||
| 116 | #include "c_api/asc_simd.h" | 116 | #include "c_api/asc_simd.h" |
| 117 | +#include "utils/std/cmath.h" | ||
| 117 | #include "acl/acl.h" | 118 | #include "acl/acl.h" |
| 118 | 119 | ||
| 119 | namespace { | 120 | namespace { |
| 121 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 122 | + | ||
| 120 | template <typename T> | 123 | template <typename T> |
| 121 | void print_data(const char* label, const std::vector<T>& values) | 124 | void print_data(const char* label, const std::vector<T>& values) |
| 122 | { | 125 | { |
| @@ -139,35 +142,53 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 139 | return true; | 142 | return true; |
| 140 | } | 143 | } |
| 141 | 144 | ||
| 142 | -constexpr uint32_t ELEMENT_COUNT = 64; | 145 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 146 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(int32_t); | ||
| 147 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 148 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(int32_t); | ||
| 149 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 150 | +constexpr uint32_t REPEAT_COUNT = | ||
| 151 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 152 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 153 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 143 | 154 | ||
| 144 | -__simd_vf__ inline void min_vf(__ubuf__ float* dst, __ubuf__ float* src0, __ubuf__ float* src1) | 155 | +__simd_vf__ inline void min_vf(__ubuf__ int32_t* dst, __ubuf__ int32_t* src0, __ubuf__ int32_t* src1, uint32_t one_repeat_size, uint16_t repeat_time) |
| 145 | { | 156 | { |
| 146 | - vector_float dst_reg; | 157 | + vector_int32_t dst_reg; |
| 147 | - vector_float src0_reg; | 158 | + vector_int32_t src0_reg; |
| 148 | - vector_float src1_reg; | 159 | + vector_int32_t src1_reg; |
| 149 | - uint32_t count = ELEMENT_COUNT; | 160 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 150 | - vector_bool mask = asc_update_mask_b32(count); | 161 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 151 | - asc_loadalign(src0_reg, src0); | 162 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 152 | - asc_loadalign(src1_reg, src1); | 163 | + const uint32_t offset = i * one_repeat_size; |
| 153 | - asc_min(dst_reg, src0_reg, src1_reg, mask); | 164 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 154 | - asc_storealign(dst, dst_reg, mask); | 165 | + asc_loadalign(src0_reg, src0 + offset); |
| 166 | + asc_loadalign(src1_reg, src1 + offset); | ||
| 167 | + asc_min(dst_reg, src0_reg, src1_reg, mask); | ||
| 168 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 169 | + } | ||
| 155 | } | 170 | } |
| 156 | 171 | ||
| 157 | -__global__ __vector__ void asc_min_kernel(__gm__ float* dst, __gm__ float* src0, __gm__ float* src1) | 172 | +__global__ __vector__ void asc_min_kernel(__gm__ int32_t* dst, __gm__ int32_t* src0, __gm__ int32_t* src1) |
| 158 | { | 173 | { |
| 159 | asc_init(); | 174 | asc_init(); |
| 160 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 175 | + __ubuf__ int32_t dst_local[PADDED_ELEMENT_COUNT]; |
| 161 | - __ubuf__ float src0_local[ELEMENT_COUNT]; | 176 | + __ubuf__ int32_t src0_local[PADDED_ELEMENT_COUNT]; |
| 162 | - __ubuf__ float src1_local[ELEMENT_COUNT]; | 177 | + __ubuf__ int32_t src1_local[PADDED_ELEMENT_COUNT]; |
| 163 | - asc_copy_gm2ub_align(src0_local, src0, ELEMENT_COUNT * sizeof(float)); | 178 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 164 | - asc_copy_gm2ub_align(src1_local, src1, ELEMENT_COUNT * sizeof(float)); | 179 | + asc_copy_gm2ub_align(src0_local, src0, TOTAL_LENGTH * sizeof(int32_t)); |
| 165 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 180 | + asc_copy_gm2ub_align(src1_local, src1, TOTAL_LENGTH * sizeof(int32_t)); |
| 166 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 181 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 167 | - min_vf(dst_local, src0_local, src1_local); | 182 | + |
| 168 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 183 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(int32_t)); |
| 169 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 184 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 170 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 185 | + asc_lock(PIPE_V, MUTEX_ID); |
| 186 | + asc_vf_call<min_vf>(dst_local, src0_local, src1_local, one_repeat_size, repeat_time); | ||
| 187 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 188 | + | ||
| 189 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 190 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(int32_t)); | ||
| 191 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 171 | asc_sync(); | 192 | asc_sync(); |
| 172 | } | 193 | } |
| 173 | 194 | ||
| @@ -175,42 +196,42 @@ __global__ __vector__ void asc_min_kernel(__gm__ float* dst, __gm__ float* src0, | |||
| 175 | 196 | ||
| 176 | int main() | 197 | int main() |
| 177 | { | 198 | { |
| 178 | - std::vector<float> src0(ELEMENT_COUNT); | 199 | + std::vector<int32_t> src0(TOTAL_LENGTH); |
| 179 | - std::vector<float> src1(ELEMENT_COUNT); | 200 | + std::vector<int32_t> src1(TOTAL_LENGTH); |
| 180 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 201 | + std::vector<int32_t> output(TOTAL_LENGTH, 0); |
| 181 | - std::vector<float> golden(ELEMENT_COUNT); | 202 | + std::vector<int32_t> golden(TOTAL_LENGTH); |
| 182 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 203 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 183 | - src0[i] = static_cast<float>(i) - 24.0f; | 204 | + src0[i] = static_cast<int32_t>(i) - 64; |
| 184 | - src1[i] = 16.0f - static_cast<float>(i) * 0.5f; | 205 | + src1[i] = 32 - static_cast<int32_t>(i); |
| 185 | - golden[i] = std::min(src0[i], src1[i]); | 206 | + golden[i] = src0[i] < src1[i] ? src0[i] : src1[i]; |
| 186 | } | 207 | } |
| 187 | 208 | ||
| 188 | aclInit(nullptr); | 209 | aclInit(nullptr); |
| 189 | aclrtSetDevice(0); | 210 | aclrtSetDevice(0); |
| 190 | - float* src0_device = nullptr; | 211 | + int32_t* src0_device = nullptr; |
| 191 | - aclrtMalloc(reinterpret_cast<void**>(&src0_device), (ELEMENT_COUNT) * sizeof(float), | 212 | + aclrtMalloc(reinterpret_cast<void**>(&src0_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 192 | ACL_MEM_MALLOC_HUGE_FIRST); | 213 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 193 | - float* src1_device = nullptr; | 214 | + int32_t* src1_device = nullptr; |
| 194 | - aclrtMalloc(reinterpret_cast<void**>(&src1_device), (ELEMENT_COUNT) * sizeof(float), | 215 | + aclrtMalloc(reinterpret_cast<void**>(&src1_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 195 | ACL_MEM_MALLOC_HUGE_FIRST); | 216 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 196 | - float* dst_device = nullptr; | 217 | + int32_t* dst_device = nullptr; |
| 197 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 218 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 198 | ACL_MEM_MALLOC_HUGE_FIRST); | 219 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 199 | - aclrtMemcpy(src0_device, src0.size() * sizeof(float), src0.data(), src0.size() * sizeof(float), | 220 | + aclrtMemcpy(src0_device, src0.size() * sizeof(int32_t), src0.data(), src0.size() * sizeof(int32_t), |
| 200 | ACL_MEMCPY_HOST_TO_DEVICE); | 221 | ACL_MEMCPY_HOST_TO_DEVICE); |
| 201 | - aclrtMemcpy(src1_device, src1.size() * sizeof(float), src1.data(), src1.size() * sizeof(float), | 222 | + aclrtMemcpy(src1_device, src1.size() * sizeof(int32_t), src1.data(), src1.size() * sizeof(int32_t), |
| 202 | ACL_MEMCPY_HOST_TO_DEVICE); | 223 | ACL_MEMCPY_HOST_TO_DEVICE); |
| 203 | 224 | ||
| 204 | asc_min_kernel<<<1, 0>>>(dst_device, src0_device, src1_device); | 225 | asc_min_kernel<<<1, 0>>>(dst_device, src0_device, src1_device); |
| 205 | aclrtSynchronizeDevice(); | 226 | aclrtSynchronizeDevice(); |
| 206 | - aclrtMemcpy(output.data(), output.size() * sizeof(float), dst_device, output.size() * sizeof(float), | 227 | + aclrtMemcpy(output.data(), output.size() * sizeof(int32_t), dst_device, output.size() * sizeof(int32_t), |
| 207 | ACL_MEMCPY_DEVICE_TO_HOST); | 228 | ACL_MEMCPY_DEVICE_TO_HOST); |
| 208 | 229 | ||
| 209 | print_data("Input src0", src0); | 230 | print_data("Input src0", src0); |
| 210 | print_data("Input src1", src1); | 231 | print_data("Input src1", src1); |
| 211 | print_data("Output", output); | 232 | print_data("Output", output); |
| 212 | print_data("Golden", golden); | 233 | print_data("Golden", golden); |
| 213 | - const bool passed = compare_data(output, golden, 1e-6); | 234 | + const bool passed = compare_data(output, golden); |
| 214 | std::cout << (passed ? "[Success] asc_min passed." : "[Failed] asc_min failed.") << std::endl; | 235 | std::cout << (passed ? "[Success] asc_min passed." : "[Failed] asc_min failed.") << std::endl; |
| 215 | aclrtFree(dst_device); | 236 | aclrtFree(dst_device); |
| 216 | aclrtFree(src0_device); | 237 | aclrtFree(src0_device); |
| @@ -109,9 +109,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 109 | #include <vector> | 109 | #include <vector> |
| 110 | 110 | ||
| 111 | #include "c_api/asc_simd.h" | 111 | #include "c_api/asc_simd.h" |
| 112 | +#include "utils/std/cmath.h" | ||
| 112 | #include "acl/acl.h" | 113 | #include "acl/acl.h" |
| 113 | 114 | ||
| 114 | namespace { | 115 | namespace { |
| 116 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 117 | + | ||
| 115 | template <typename T> | 118 | template <typename T> |
| 116 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) | 119 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) |
| 117 | { | 120 | { |
| @@ -124,32 +127,50 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 124 | return true; | 127 | return true; |
| 125 | } | 128 | } |
| 126 | 129 | ||
| 127 | -constexpr uint32_t ELEMENT_COUNT = 64; | 130 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 131 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(float); | ||
| 132 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 133 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(float); | ||
| 134 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 135 | +constexpr uint32_t REPEAT_COUNT = | ||
| 136 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 137 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 138 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 128 | constexpr float SCALAR_VALUE = 3.0f; | 139 | constexpr float SCALAR_VALUE = 3.0f; |
| 129 | 140 | ||
| 130 | -__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src) | 141 | +__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src, uint32_t one_repeat_size, uint16_t repeat_time) |
| 131 | { | 142 | { |
| 132 | vector_float dst_reg; | 143 | vector_float dst_reg; |
| 133 | vector_float src_reg; | 144 | vector_float src_reg; |
| 134 | - uint32_t count = ELEMENT_COUNT; | 145 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 135 | - vector_bool mask = asc_update_mask_b32(count); | 146 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 136 | - asc_loadalign(src_reg, src); | 147 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 137 | - asc_min_scalar(dst_reg, src_reg, SCALAR_VALUE, mask); | 148 | + const uint32_t offset = i * one_repeat_size; |
| 138 | - asc_storealign(dst, dst_reg, mask); | 149 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 150 | + asc_loadalign(src_reg, src + offset); | ||
| 151 | + asc_min_scalar(dst_reg, src_reg, SCALAR_VALUE, mask); | ||
| 152 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 153 | + } | ||
| 139 | } | 154 | } |
| 140 | 155 | ||
| 141 | __global__ __vector__ void asc_min_scalar_kernel(__gm__ float* dst, __gm__ float* src) | 156 | __global__ __vector__ void asc_min_scalar_kernel(__gm__ float* dst, __gm__ float* src) |
| 142 | { | 157 | { |
| 143 | asc_init(); | 158 | asc_init(); |
| 144 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 159 | + __ubuf__ float dst_local[PADDED_ELEMENT_COUNT]; |
| 145 | - __ubuf__ float src_local[ELEMENT_COUNT]; | 160 | + __ubuf__ float src_local[PADDED_ELEMENT_COUNT]; |
| 146 | - asc_copy_gm2ub_align(src_local, src, ELEMENT_COUNT * sizeof(float)); | 161 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 147 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 162 | + asc_copy_gm2ub_align(src_local, src, TOTAL_LENGTH * sizeof(float)); |
| 148 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 163 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 149 | - compute(dst_local, src_local); | 164 | + |
| 150 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 165 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(float)); |
| 151 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 166 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 152 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 167 | + asc_lock(PIPE_V, MUTEX_ID); |
| 168 | + asc_vf_call<compute>(dst_local, src_local, one_repeat_size, repeat_time); | ||
| 169 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 170 | + | ||
| 171 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 172 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(float)); | ||
| 173 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 153 | asc_sync(); | 174 | asc_sync(); |
| 154 | } | 175 | } |
| 155 | 176 | ||
| @@ -157,10 +178,10 @@ __global__ __vector__ void asc_min_scalar_kernel(__gm__ float* dst, __gm__ float | |||
| 157 | 178 | ||
| 158 | int main() | 179 | int main() |
| 159 | { | 180 | { |
| 160 | - std::vector<float> src(ELEMENT_COUNT); | 181 | + std::vector<float> src(TOTAL_LENGTH); |
| 161 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 182 | + std::vector<float> output(TOTAL_LENGTH, 0.0f); |
| 162 | - std::vector<float> golden(ELEMENT_COUNT); | 183 | + std::vector<float> golden(TOTAL_LENGTH); |
| 163 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 184 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 164 | src[i] = static_cast<float>(i) - 24.0f; | 185 | src[i] = static_cast<float>(i) - 24.0f; |
| 165 | golden[i] = std::min(src[i], SCALAR_VALUE); | 186 | golden[i] = std::min(src[i], SCALAR_VALUE); |
| 166 | } | 187 | } |
| @@ -168,10 +189,10 @@ int main() | |||
| 168 | aclInit(nullptr); | 189 | aclInit(nullptr); |
| 169 | aclrtSetDevice(0); | 190 | aclrtSetDevice(0); |
| 170 | float* src_device = nullptr; | 191 | float* src_device = nullptr; |
| 171 | - aclrtMalloc(reinterpret_cast<void**>(&src_device), (ELEMENT_COUNT) * sizeof(float), | 192 | + aclrtMalloc(reinterpret_cast<void**>(&src_device), (TOTAL_LENGTH) * sizeof(float), |
| 172 | ACL_MEM_MALLOC_HUGE_FIRST); | 193 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 173 | float* dst_device = nullptr; | 194 | float* dst_device = nullptr; |
| 174 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 195 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(float), |
| 175 | ACL_MEM_MALLOC_HUGE_FIRST); | 196 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 176 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), | 197 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), |
| 177 | ACL_MEMCPY_HOST_TO_DEVICE); | 198 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -114,9 +114,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 114 | #include <vector> | 114 | #include <vector> |
| 115 | 115 | ||
| 116 | #include "c_api/asc_simd.h" | 116 | #include "c_api/asc_simd.h" |
| 117 | +#include "utils/std/cmath.h" | ||
| 117 | #include "acl/acl.h" | 118 | #include "acl/acl.h" |
| 118 | 119 | ||
| 119 | namespace { | 120 | namespace { |
| 121 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 122 | + | ||
| 120 | template <typename T> | 123 | template <typename T> |
| 121 | void print_data(const char* label, const std::vector<T>& values) | 124 | void print_data(const char* label, const std::vector<T>& values) |
| 122 | { | 125 | { |
| @@ -139,35 +142,53 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 139 | return true; | 142 | return true; |
| 140 | } | 143 | } |
| 141 | 144 | ||
| 142 | -constexpr uint32_t ELEMENT_COUNT = 64; | 145 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 146 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(int32_t); | ||
| 147 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 148 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(int32_t); | ||
| 149 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 150 | +constexpr uint32_t REPEAT_COUNT = | ||
| 151 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 152 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 153 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 143 | 154 | ||
| 144 | -__simd_vf__ inline void mul_vf(__ubuf__ float* dst, __ubuf__ float* src0, __ubuf__ float* src1) | 155 | +__simd_vf__ inline void mul_vf(__ubuf__ int32_t* dst, __ubuf__ int32_t* src0, __ubuf__ int32_t* src1, uint32_t one_repeat_size, uint16_t repeat_time) |
| 145 | { | 156 | { |
| 146 | - vector_float dst_reg; | 157 | + vector_int32_t dst_reg; |
| 147 | - vector_float src0_reg; | 158 | + vector_int32_t src0_reg; |
| 148 | - vector_float src1_reg; | 159 | + vector_int32_t src1_reg; |
| 149 | - uint32_t count = ELEMENT_COUNT; | 160 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 150 | - vector_bool mask = asc_update_mask_b32(count); | 161 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 151 | - asc_loadalign(src0_reg, src0); | 162 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 152 | - asc_loadalign(src1_reg, src1); | 163 | + const uint32_t offset = i * one_repeat_size; |
| 153 | - asc_mul(dst_reg, src0_reg, src1_reg, mask); | 164 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 154 | - asc_storealign(dst, dst_reg, mask); | 165 | + asc_loadalign(src0_reg, src0 + offset); |
| 166 | + asc_loadalign(src1_reg, src1 + offset); | ||
| 167 | + asc_mul(dst_reg, src0_reg, src1_reg, mask); | ||
| 168 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 169 | + } | ||
| 155 | } | 170 | } |
| 156 | 171 | ||
| 157 | -__global__ __vector__ void asc_mul_kernel(__gm__ float* dst, __gm__ float* src0, __gm__ float* src1) | 172 | +__global__ __vector__ void asc_mul_kernel(__gm__ int32_t* dst, __gm__ int32_t* src0, __gm__ int32_t* src1) |
| 158 | { | 173 | { |
| 159 | asc_init(); | 174 | asc_init(); |
| 160 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 175 | + __ubuf__ int32_t dst_local[PADDED_ELEMENT_COUNT]; |
| 161 | - __ubuf__ float src0_local[ELEMENT_COUNT]; | 176 | + __ubuf__ int32_t src0_local[PADDED_ELEMENT_COUNT]; |
| 162 | - __ubuf__ float src1_local[ELEMENT_COUNT]; | 177 | + __ubuf__ int32_t src1_local[PADDED_ELEMENT_COUNT]; |
| 163 | - asc_copy_gm2ub_align(src0_local, src0, ELEMENT_COUNT * sizeof(float)); | 178 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 164 | - asc_copy_gm2ub_align(src1_local, src1, ELEMENT_COUNT * sizeof(float)); | 179 | + asc_copy_gm2ub_align(src0_local, src0, TOTAL_LENGTH * sizeof(int32_t)); |
| 165 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 180 | + asc_copy_gm2ub_align(src1_local, src1, TOTAL_LENGTH * sizeof(int32_t)); |
| 166 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 181 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 167 | - mul_vf(dst_local, src0_local, src1_local); | 182 | + |
| 168 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 183 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(int32_t)); |
| 169 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 184 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 170 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 185 | + asc_lock(PIPE_V, MUTEX_ID); |
| 186 | + asc_vf_call<mul_vf>(dst_local, src0_local, src1_local, one_repeat_size, repeat_time); | ||
| 187 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 188 | + | ||
| 189 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 190 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(int32_t)); | ||
| 191 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 171 | asc_sync(); | 192 | asc_sync(); |
| 172 | } | 193 | } |
| 173 | 194 | ||
| @@ -175,11 +196,11 @@ __global__ __vector__ void asc_mul_kernel(__gm__ float* dst, __gm__ float* src0, | |||
| 175 | 196 | ||
| 176 | int main() | 197 | int main() |
| 177 | { | 198 | { |
| 178 | - std::vector<float> src0(ELEMENT_COUNT); | 199 | + std::vector<int32_t> src0(TOTAL_LENGTH); |
| 179 | - std::vector<float> src1(ELEMENT_COUNT); | 200 | + std::vector<int32_t> src1(TOTAL_LENGTH); |
| 180 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 201 | + std::vector<int32_t> output(TOTAL_LENGTH, 0); |
| 181 | - std::vector<float> golden(ELEMENT_COUNT); | 202 | + std::vector<int32_t> golden(TOTAL_LENGTH); |
| 182 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 203 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 183 | src0[i] = static_cast<float>(i) * 0.25f; | 204 | src0[i] = static_cast<float>(i) * 0.25f; |
| 184 | src1[i] = static_cast<float>(i % 8) * 0.5f; | 205 | src1[i] = static_cast<float>(i % 8) * 0.5f; |
| 185 | golden[i] = src0[i] * src1[i]; | 206 | golden[i] = src0[i] * src1[i]; |
| @@ -187,30 +208,30 @@ int main() | |||
| 187 | 208 | ||
| 188 | aclInit(nullptr); | 209 | aclInit(nullptr); |
| 189 | aclrtSetDevice(0); | 210 | aclrtSetDevice(0); |
| 190 | - float* src0_device = nullptr; | 211 | + int32_t* src0_device = nullptr; |
| 191 | - aclrtMalloc(reinterpret_cast<void**>(&src0_device), (ELEMENT_COUNT) * sizeof(float), | 212 | + aclrtMalloc(reinterpret_cast<void**>(&src0_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 192 | ACL_MEM_MALLOC_HUGE_FIRST); | 213 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 193 | - float* src1_device = nullptr; | 214 | + int32_t* src1_device = nullptr; |
| 194 | - aclrtMalloc(reinterpret_cast<void**>(&src1_device), (ELEMENT_COUNT) * sizeof(float), | 215 | + aclrtMalloc(reinterpret_cast<void**>(&src1_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 195 | ACL_MEM_MALLOC_HUGE_FIRST); | 216 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 196 | - float* dst_device = nullptr; | 217 | + int32_t* dst_device = nullptr; |
| 197 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 218 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 198 | ACL_MEM_MALLOC_HUGE_FIRST); | 219 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 199 | - aclrtMemcpy(src0_device, src0.size() * sizeof(float), src0.data(), src0.size() * sizeof(float), | 220 | + aclrtMemcpy(src0_device, src0.size() * sizeof(int32_t), src0.data(), src0.size() * sizeof(int32_t), |
| 200 | ACL_MEMCPY_HOST_TO_DEVICE); | 221 | ACL_MEMCPY_HOST_TO_DEVICE); |
| 201 | - aclrtMemcpy(src1_device, src1.size() * sizeof(float), src1.data(), src1.size() * sizeof(float), | 222 | + aclrtMemcpy(src1_device, src1.size() * sizeof(int32_t), src1.data(), src1.size() * sizeof(int32_t), |
| 202 | ACL_MEMCPY_HOST_TO_DEVICE); | 223 | ACL_MEMCPY_HOST_TO_DEVICE); |
| 203 | 224 | ||
| 204 | asc_mul_kernel<<<1, 0>>>(dst_device, src0_device, src1_device); | 225 | asc_mul_kernel<<<1, 0>>>(dst_device, src0_device, src1_device); |
| 205 | aclrtSynchronizeDevice(); | 226 | aclrtSynchronizeDevice(); |
| 206 | - aclrtMemcpy(output.data(), output.size() * sizeof(float), dst_device, output.size() * sizeof(float), | 227 | + aclrtMemcpy(output.data(), output.size() * sizeof(int32_t), dst_device, output.size() * sizeof(int32_t), |
| 207 | ACL_MEMCPY_DEVICE_TO_HOST); | 228 | ACL_MEMCPY_DEVICE_TO_HOST); |
| 208 | 229 | ||
| 209 | print_data("Input src0", src0); | 230 | print_data("Input src0", src0); |
| 210 | print_data("Input src1", src1); | 231 | print_data("Input src1", src1); |
| 211 | print_data("Output", output); | 232 | print_data("Output", output); |
| 212 | print_data("Golden", golden); | 233 | print_data("Golden", golden); |
| 213 | - const bool passed = compare_data(output, golden, 1e-6); | 234 | + const bool passed = compare_data(output, golden); |
| 214 | std::cout << (passed ? "[Success] asc_mul passed." : "[Failed] asc_mul failed.") << std::endl; | 235 | std::cout << (passed ? "[Success] asc_mul passed." : "[Failed] asc_mul failed.") << std::endl; |
| 215 | aclrtFree(dst_device); | 236 | aclrtFree(dst_device); |
| 216 | aclrtFree(src0_device); | 237 | aclrtFree(src0_device); |
| @@ -108,9 +108,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 108 | #include <vector> | 108 | #include <vector> |
| 109 | 109 | ||
| 110 | #include "c_api/asc_simd.h" | 110 | #include "c_api/asc_simd.h" |
| 111 | +#include "utils/std/cmath.h" | ||
| 111 | #include "acl/acl.h" | 112 | #include "acl/acl.h" |
| 112 | 113 | ||
| 113 | namespace { | 114 | namespace { |
| 115 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 116 | + | ||
| 114 | template <typename T> | 117 | template <typename T> |
| 115 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) | 118 | bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0) |
| 116 | { | 119 | { |
| @@ -123,32 +126,50 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 123 | return true; | 126 | return true; |
| 124 | } | 127 | } |
| 125 | 128 | ||
| 126 | -constexpr uint32_t ELEMENT_COUNT = 64; | 129 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 130 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(float); | ||
| 131 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 132 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(float); | ||
| 133 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 134 | +constexpr uint32_t REPEAT_COUNT = | ||
| 135 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 136 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 137 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 127 | constexpr float SCALAR_VALUE = 2.0f; | 138 | constexpr float SCALAR_VALUE = 2.0f; |
| 128 | 139 | ||
| 129 | -__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src) | 140 | +__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src, uint32_t one_repeat_size, uint16_t repeat_time) |
| 130 | { | 141 | { |
| 131 | vector_float dst_reg; | 142 | vector_float dst_reg; |
| 132 | vector_float src_reg; | 143 | vector_float src_reg; |
| 133 | - uint32_t count = ELEMENT_COUNT; | 144 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 134 | - vector_bool mask = asc_update_mask_b32(count); | 145 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 135 | - asc_loadalign(src_reg, src); | 146 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 136 | - asc_mul_scalar(dst_reg, src_reg, SCALAR_VALUE, mask); | 147 | + const uint32_t offset = i * one_repeat_size; |
| 137 | - asc_storealign(dst, dst_reg, mask); | 148 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 149 | + asc_loadalign(src_reg, src + offset); | ||
| 150 | + asc_mul_scalar(dst_reg, src_reg, SCALAR_VALUE, mask); | ||
| 151 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 152 | + } | ||
| 138 | } | 153 | } |
| 139 | 154 | ||
| 140 | __global__ __vector__ void asc_mul_scalar_kernel(__gm__ float* dst, __gm__ float* src) | 155 | __global__ __vector__ void asc_mul_scalar_kernel(__gm__ float* dst, __gm__ float* src) |
| 141 | { | 156 | { |
| 142 | asc_init(); | 157 | asc_init(); |
| 143 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 158 | + __ubuf__ float dst_local[PADDED_ELEMENT_COUNT]; |
| 144 | - __ubuf__ float src_local[ELEMENT_COUNT]; | 159 | + __ubuf__ float src_local[PADDED_ELEMENT_COUNT]; |
| 145 | - asc_copy_gm2ub_align(src_local, src, ELEMENT_COUNT * sizeof(float)); | 160 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 146 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 161 | + asc_copy_gm2ub_align(src_local, src, TOTAL_LENGTH * sizeof(float)); |
| 147 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 162 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 148 | - compute(dst_local, src_local); | 163 | + |
| 149 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 164 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(float)); |
| 150 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 165 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 151 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 166 | + asc_lock(PIPE_V, MUTEX_ID); |
| 167 | + asc_vf_call<compute>(dst_local, src_local, one_repeat_size, repeat_time); | ||
| 168 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 169 | + | ||
| 170 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 171 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(float)); | ||
| 172 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 152 | asc_sync(); | 173 | asc_sync(); |
| 153 | } | 174 | } |
| 154 | 175 | ||
| @@ -156,10 +177,10 @@ __global__ __vector__ void asc_mul_scalar_kernel(__gm__ float* dst, __gm__ float | |||
| 156 | 177 | ||
| 157 | int main() | 178 | int main() |
| 158 | { | 179 | { |
| 159 | - std::vector<float> src(ELEMENT_COUNT); | 180 | + std::vector<float> src(TOTAL_LENGTH); |
| 160 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 181 | + std::vector<float> output(TOTAL_LENGTH, 0.0f); |
| 161 | - std::vector<float> golden(ELEMENT_COUNT); | 182 | + std::vector<float> golden(TOTAL_LENGTH); |
| 162 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 183 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 163 | src[i] = (static_cast<int>(i) - 16) * 0.25f; | 184 | src[i] = (static_cast<int>(i) - 16) * 0.25f; |
| 164 | golden[i] = src[i] * SCALAR_VALUE; | 185 | golden[i] = src[i] * SCALAR_VALUE; |
| 165 | } | 186 | } |
| @@ -167,10 +188,10 @@ int main() | |||
| 167 | aclInit(nullptr); | 188 | aclInit(nullptr); |
| 168 | aclrtSetDevice(0); | 189 | aclrtSetDevice(0); |
| 169 | float* src_device = nullptr; | 190 | float* src_device = nullptr; |
| 170 | - aclrtMalloc(reinterpret_cast<void**>(&src_device), (ELEMENT_COUNT) * sizeof(float), | 191 | + aclrtMalloc(reinterpret_cast<void**>(&src_device), (TOTAL_LENGTH) * sizeof(float), |
| 171 | ACL_MEM_MALLOC_HUGE_FIRST); | 192 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 172 | float* dst_device = nullptr; | 193 | float* dst_device = nullptr; |
| 173 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 194 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(float), |
| 174 | ACL_MEM_MALLOC_HUGE_FIRST); | 195 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 175 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), | 196 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), |
| 176 | ACL_MEMCPY_HOST_TO_DEVICE); | 197 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -118,27 +118,43 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 118 | #include <iostream> | 118 | #include <iostream> |
| 119 | #include <vector> | 119 | #include <vector> |
| 120 | #include "c_api/asc_simd.h" | 120 | #include "c_api/asc_simd.h" |
| 121 | +#include "utils/std/cmath.h" | ||
| 121 | #include "acl/acl.h" | 122 | #include "acl/acl.h" |
| 122 | 123 | ||
| 123 | namespace { | 124 | namespace { |
| 124 | -constexpr uint32_t ELEMENT_COUNT = 64; | 125 | +constexpr uint8_t MUTEX_ID = 0; |
| 125 | -constexpr uint32_t BUFFER_BYTES = ELEMENT_COUNT * sizeof(uint32_t); | 126 | + |
| 127 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; | ||
| 128 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(uint32_t); | ||
| 129 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 130 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(uint32_t); | ||
| 131 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 132 | +constexpr uint32_t REPEAT_COUNT = | ||
| 133 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 134 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 135 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 136 | +constexpr uint32_t BUFFER_BYTES = TOTAL_LENGTH * sizeof(uint32_t); | ||
| 126 | 137 | ||
| 127 | __simd_vf__ inline void mull_vf(__ubuf__ uint32_t* output_low, | 138 | __simd_vf__ inline void mull_vf(__ubuf__ uint32_t* output_low, |
| 128 | __ubuf__ uint32_t* output_high, | 139 | __ubuf__ uint32_t* output_high, |
| 129 | __ubuf__ uint32_t* input0, | 140 | __ubuf__ uint32_t* input0, |
| 130 | - __ubuf__ uint32_t* input1) | 141 | + __ubuf__ uint32_t* input1, uint32_t one_repeat_size, uint16_t repeat_time) |
| 131 | { | 142 | { |
| 132 | vector_uint32_t src0; | 143 | vector_uint32_t src0; |
| 133 | vector_uint32_t src1; | 144 | vector_uint32_t src1; |
| 134 | vector_uint32_t dst0; | 145 | vector_uint32_t dst0; |
| 135 | vector_uint32_t dst1; | 146 | vector_uint32_t dst1; |
| 136 | - vector_bool mask = asc_create_mask_b32(PAT_ALL); | 147 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 137 | - asc_loadalign(src0, input0); | 148 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 138 | - asc_loadalign(src1, input1); | 149 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 139 | - asc_mull(dst0, dst1, src0, src1, mask); | 150 | + const uint32_t offset = i * one_repeat_size; |
| 140 | - asc_storealign(output_low, dst0, mask); | 151 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 141 | - asc_storealign(output_high, dst1, mask); | 152 | + asc_loadalign(src0, input0 + offset); |
| 153 | + asc_loadalign(src1, input1 + offset); | ||
| 154 | + asc_mull(dst0, dst1, src0, src1, mask); | ||
| 155 | + asc_storealign(output_low + offset, dst0, mask); | ||
| 156 | + asc_storealign(output_high + offset, dst1, mask); | ||
| 157 | + } | ||
| 142 | } | 158 | } |
| 143 | 159 | ||
| 144 | __global__ __vector__ void asc_mull_kernel(__gm__ uint32_t* output_low, | 160 | __global__ __vector__ void asc_mull_kernel(__gm__ uint32_t* output_low, |
| @@ -147,30 +163,36 @@ __global__ __vector__ void asc_mull_kernel(__gm__ uint32_t* output_low, | |||
| 147 | __gm__ uint32_t* input1) | 163 | __gm__ uint32_t* input1) |
| 148 | { | 164 | { |
| 149 | asc_init(); | 165 | asc_init(); |
| 150 | - __ubuf__ uint32_t output_low_local[ELEMENT_COUNT]; | 166 | + __ubuf__ uint32_t output_low_local[PADDED_ELEMENT_COUNT]; |
| 151 | - __ubuf__ uint32_t output_high_local[ELEMENT_COUNT]; | 167 | + __ubuf__ uint32_t output_high_local[PADDED_ELEMENT_COUNT]; |
| 152 | - __ubuf__ uint32_t input0_local[ELEMENT_COUNT]; | 168 | + __ubuf__ uint32_t input0_local[PADDED_ELEMENT_COUNT]; |
| 153 | - __ubuf__ uint32_t input1_local[ELEMENT_COUNT]; | 169 | + __ubuf__ uint32_t input1_local[PADDED_ELEMENT_COUNT]; |
| 170 | + asc_lock(PIPE_MTE2, MUTEX_ID); | ||
| 154 | asc_copy_gm2ub_align(input0_local, input0, BUFFER_BYTES); | 171 | asc_copy_gm2ub_align(input0_local, input0, BUFFER_BYTES); |
| 155 | asc_copy_gm2ub_align(input1_local, input1, BUFFER_BYTES); | 172 | asc_copy_gm2ub_align(input1_local, input1, BUFFER_BYTES); |
| 156 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 173 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 157 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 174 | + |
| 158 | - mull_vf(output_low_local, output_high_local, input0_local, input1_local); | 175 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(uint32_t)); |
| 159 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 176 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 160 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 177 | + asc_lock(PIPE_V, MUTEX_ID); |
| 178 | + asc_vf_call<mull_vf>(output_low_local, output_high_local, input0_local, input1_local, one_repeat_size, repeat_time); | ||
| 179 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 180 | + | ||
| 181 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 161 | asc_copy_ub2gm_align(output_low, output_low_local, BUFFER_BYTES); | 182 | asc_copy_ub2gm_align(output_low, output_low_local, BUFFER_BYTES); |
| 162 | asc_copy_ub2gm_align(output_high, output_high_local, BUFFER_BYTES); | 183 | asc_copy_ub2gm_align(output_high, output_high_local, BUFFER_BYTES); |
| 184 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 163 | asc_sync(); | 185 | asc_sync(); |
| 164 | } | 186 | } |
| 165 | } // namespace | 187 | } // namespace |
| 166 | 188 | ||
| 167 | int main() | 189 | int main() |
| 168 | { | 190 | { |
| 169 | - std::vector<uint32_t> input0(ELEMENT_COUNT); | 191 | + std::vector<uint32_t> input0(TOTAL_LENGTH); |
| 170 | - std::vector<uint32_t> input1(ELEMENT_COUNT); | 192 | + std::vector<uint32_t> input1(TOTAL_LENGTH); |
| 171 | - std::vector<uint32_t> output_low(ELEMENT_COUNT, 0); | 193 | + std::vector<uint32_t> output_low(TOTAL_LENGTH, 0); |
| 172 | - std::vector<uint32_t> output_high(ELEMENT_COUNT, 0); | 194 | + std::vector<uint32_t> output_high(TOTAL_LENGTH, 0); |
| 173 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 195 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 174 | input0[i] = i + 1; | 196 | input0[i] = i + 1; |
| 175 | input1[i] = 0x10000000U + i; | 197 | input1[i] = 0x10000000U + i; |
| 176 | } | 198 | } |
| @@ -193,7 +215,7 @@ int main() | |||
| 193 | aclrtMemcpy(output_high.data(), BUFFER_BYTES, output_high_device, BUFFER_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); | 215 | aclrtMemcpy(output_high.data(), BUFFER_BYTES, output_high_device, BUFFER_BYTES, ACL_MEMCPY_DEVICE_TO_HOST); |
| 194 | 216 | ||
| 195 | bool passed = true; | 217 | bool passed = true; |
| 196 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 218 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 197 | const uint64_t expected = static_cast<uint64_t>(input0[i]) * input1[i]; | 219 | const uint64_t expected = static_cast<uint64_t>(input0[i]) * input1[i]; |
| 198 | if (output_low[i] != static_cast<uint32_t>(expected) || | 220 | if (output_low[i] != static_cast<uint32_t>(expected) || |
| 199 | output_high[i] != static_cast<uint32_t>(expected >> 32)) { | 221 | output_high[i] != static_cast<uint32_t>(expected >> 32)) { |
| @@ -111,9 +111,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 111 | #include <vector> | 111 | #include <vector> |
| 112 | 112 | ||
| 113 | #include "c_api/asc_simd.h" | 113 | #include "c_api/asc_simd.h" |
| 114 | +#include "utils/std/cmath.h" | ||
| 114 | #include "acl/acl.h" | 115 | #include "acl/acl.h" |
| 115 | 116 | ||
| 116 | namespace { | 117 | namespace { |
| 118 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 119 | + | ||
| 117 | template <typename T> | 120 | template <typename T> |
| 118 | void print_data(const char* label, const std::vector<T>& values) | 121 | void print_data(const char* label, const std::vector<T>& values) |
| 119 | { | 122 | { |
| @@ -136,31 +139,49 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 136 | return true; | 139 | return true; |
| 137 | } | 140 | } |
| 138 | 141 | ||
| 139 | -constexpr uint32_t ELEMENT_COUNT = 64; | 142 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 143 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(float); | ||
| 144 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 145 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(float); | ||
| 146 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 147 | +constexpr uint32_t REPEAT_COUNT = | ||
| 148 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 149 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 150 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 140 | 151 | ||
| 141 | -__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src) | 152 | +__simd_vf__ inline void compute(__ubuf__ float* dst, __ubuf__ float* src, uint32_t one_repeat_size, uint16_t repeat_time) |
| 142 | { | 153 | { |
| 143 | vector_float dst_reg; | 154 | vector_float dst_reg; |
| 144 | vector_float src_reg; | 155 | vector_float src_reg; |
| 145 | - uint32_t count = ELEMENT_COUNT; | 156 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 146 | - vector_bool mask = asc_update_mask_b32(count); | 157 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 147 | - asc_loadalign(src_reg, src); | 158 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 148 | - asc_neg(dst_reg, src_reg, mask); | 159 | + const uint32_t offset = i * one_repeat_size; |
| 149 | - asc_storealign(dst, dst_reg, mask); | 160 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 161 | + asc_loadalign(src_reg, src + offset); | ||
| 162 | + asc_neg(dst_reg, src_reg, mask); | ||
| 163 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 164 | + } | ||
| 150 | } | 165 | } |
| 151 | 166 | ||
| 152 | __global__ __vector__ void asc_neg_kernel(__gm__ float* dst, __gm__ float* src) | 167 | __global__ __vector__ void asc_neg_kernel(__gm__ float* dst, __gm__ float* src) |
| 153 | { | 168 | { |
| 154 | asc_init(); | 169 | asc_init(); |
| 155 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 170 | + __ubuf__ float dst_local[PADDED_ELEMENT_COUNT]; |
| 156 | - __ubuf__ float src_local[ELEMENT_COUNT]; | 171 | + __ubuf__ float src_local[PADDED_ELEMENT_COUNT]; |
| 157 | - asc_copy_gm2ub_align(src_local, src, ELEMENT_COUNT * sizeof(float)); | 172 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 158 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 173 | + asc_copy_gm2ub_align(src_local, src, TOTAL_LENGTH * sizeof(float)); |
| 159 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 174 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 160 | - compute(dst_local, src_local); | 175 | + |
| 161 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 176 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(float)); |
| 162 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 177 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 163 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 178 | + asc_lock(PIPE_V, MUTEX_ID); |
| 179 | + asc_vf_call<compute>(dst_local, src_local, one_repeat_size, repeat_time); | ||
| 180 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 181 | + | ||
| 182 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 183 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(float)); | ||
| 184 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 164 | asc_sync(); | 185 | asc_sync(); |
| 165 | } | 186 | } |
| 166 | 187 | ||
| @@ -168,10 +189,10 @@ __global__ __vector__ void asc_neg_kernel(__gm__ float* dst, __gm__ float* src) | |||
| 168 | 189 | ||
| 169 | int main() | 190 | int main() |
| 170 | { | 191 | { |
| 171 | - std::vector<float> src(ELEMENT_COUNT); | 192 | + std::vector<float> src(TOTAL_LENGTH); |
| 172 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 193 | + std::vector<float> output(TOTAL_LENGTH, 0.0f); |
| 173 | - std::vector<float> golden(ELEMENT_COUNT); | 194 | + std::vector<float> golden(TOTAL_LENGTH); |
| 174 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 195 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 175 | src[i] = (static_cast<int>(i) - 32) * 0.25f; | 196 | src[i] = (static_cast<int>(i) - 32) * 0.25f; |
| 176 | golden[i] = -src[i]; | 197 | golden[i] = -src[i]; |
| 177 | } | 198 | } |
| @@ -179,10 +200,10 @@ int main() | |||
| 179 | aclInit(nullptr); | 200 | aclInit(nullptr); |
| 180 | aclrtSetDevice(0); | 201 | aclrtSetDevice(0); |
| 181 | float* src_device = nullptr; | 202 | float* src_device = nullptr; |
| 182 | - aclrtMalloc(reinterpret_cast<void**>(&src_device), (ELEMENT_COUNT) * sizeof(float), | 203 | + aclrtMalloc(reinterpret_cast<void**>(&src_device), (TOTAL_LENGTH) * sizeof(float), |
| 183 | ACL_MEM_MALLOC_HUGE_FIRST); | 204 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 184 | float* dst_device = nullptr; | 205 | float* dst_device = nullptr; |
| 185 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 206 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(float), |
| 186 | ACL_MEM_MALLOC_HUGE_FIRST); | 207 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 187 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), | 208 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), |
| 188 | ACL_MEMCPY_HOST_TO_DEVICE); | 209 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -101,6 +101,8 @@ __simd_callee__ inline vector_float asc_sqrt(vector_float src, | |||
| 101 | ```bash | 101 | ```bash |
| 102 | bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main | 102 | bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main |
| 103 | ``` | 103 | ``` |
| 104 | + | ||
| 105 | +**注意:** 本示例主机侧golden计算会调用需由libm提供的数学函数:`std::sqrt`,编译命令需要保留`-lm`以链接数学库。 | ||
| 104 | <!-- end id8 --> | 106 | <!-- end id8 --> |
| 105 | 107 | ||
| 106 | ```c | 108 | ```c |
| @@ -111,9 +113,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main | |||
| 111 | #include <vector> | 113 | #include <vector> |
| 112 | 114 | ||
| 113 | #include "c_api/asc_simd.h" | 115 | #include "c_api/asc_simd.h" |
| 116 | +#include "utils/std/cmath.h" | ||
| 114 | #include "acl/acl.h" | 117 | #include "acl/acl.h" |
| 115 | 118 | ||
| 116 | namespace { | 119 | namespace { |
| 120 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 121 | + | ||
| 117 | template <typename T> | 122 | template <typename T> |
| 118 | void print_data(const char* label, const std::vector<T>& values) | 123 | void print_data(const char* label, const std::vector<T>& values) |
| 119 | { | 124 | { |
| @@ -136,41 +141,59 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, | |||
| 136 | return true; | 141 | return true; |
| 137 | } | 142 | } |
| 138 | 143 | ||
| 139 | -constexpr uint32_t ELEMENT_COUNT = 64; | 144 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 145 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(float); | ||
| 146 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 147 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(float); | ||
| 148 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 149 | +constexpr uint32_t REPEAT_COUNT = | ||
| 150 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 151 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 152 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 140 | 153 | ||
| 141 | -__simd_vf__ inline void sqrt_vf(__ubuf__ float* dst, __ubuf__ float* src) | 154 | +__simd_vf__ inline void sqrt_vf(__ubuf__ float* dst, __ubuf__ float* src, uint32_t one_repeat_size, uint16_t repeat_time) |
| 142 | { | 155 | { |
| 143 | vector_float dst_reg; | 156 | vector_float dst_reg; |
| 144 | vector_float src_reg; | 157 | vector_float src_reg; |
| 145 | - uint32_t count = ELEMENT_COUNT; | 158 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 146 | - vector_bool mask = asc_update_mask_b32(count); | 159 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 147 | - asc_loadalign(src_reg, src); | 160 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 148 | - asc_sqrt(dst_reg, src_reg, mask); | 161 | + const uint32_t offset = i * one_repeat_size; |
| 149 | - asc_storealign(dst, dst_reg, mask); | 162 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 163 | + asc_loadalign(src_reg, src + offset); | ||
| 164 | + asc_sqrt(dst_reg, src_reg, mask); | ||
| 165 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 166 | + } | ||
| 150 | } | 167 | } |
| 151 | 168 | ||
| 152 | __global__ __vector__ void asc_sqrt_kernel(__gm__ float* dst, __gm__ float* src) | 169 | __global__ __vector__ void asc_sqrt_kernel(__gm__ float* dst, __gm__ float* src) |
| 153 | { | 170 | { |
| 154 | asc_init(); | 171 | asc_init(); |
| 155 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 172 | + __ubuf__ float dst_local[PADDED_ELEMENT_COUNT]; |
| 156 | - __ubuf__ float src_local[ELEMENT_COUNT]; | 173 | + __ubuf__ float src_local[PADDED_ELEMENT_COUNT]; |
| 157 | - asc_copy_gm2ub_align(src_local, src, ELEMENT_COUNT * sizeof(float)); | 174 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 158 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 175 | + asc_copy_gm2ub_align(src_local, src, TOTAL_LENGTH * sizeof(float)); |
| 159 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 176 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 160 | - sqrt_vf(dst_local, src_local); | 177 | + |
| 161 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 178 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(float)); |
| 162 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 179 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 163 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 180 | + asc_lock(PIPE_V, MUTEX_ID); |
| 181 | + asc_vf_call<sqrt_vf>(dst_local, src_local, one_repeat_size, repeat_time); | ||
| 182 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 183 | + | ||
| 184 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 185 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(float)); | ||
| 186 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 164 | asc_sync(); | 187 | asc_sync(); |
| 165 | } | 188 | } |
| 166 | } // namespace | 189 | } // namespace |
| 167 | 190 | ||
| 168 | int main() | 191 | int main() |
| 169 | { | 192 | { |
| 170 | - std::vector<float> src(ELEMENT_COUNT); | 193 | + std::vector<float> src(TOTAL_LENGTH); |
| 171 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 194 | + std::vector<float> output(TOTAL_LENGTH, 0.0f); |
| 172 | - std::vector<float> golden(ELEMENT_COUNT); | 195 | + std::vector<float> golden(TOTAL_LENGTH); |
| 173 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 196 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 174 | src[i] = static_cast<float>((i % 8) * (i % 8)); | 197 | src[i] = static_cast<float>((i % 8) * (i % 8)); |
| 175 | golden[i] = std::sqrt(src[i]); | 198 | golden[i] = std::sqrt(src[i]); |
| 176 | } | 199 | } |
| @@ -178,10 +201,10 @@ int main() | |||
| 178 | aclInit(nullptr); | 201 | aclInit(nullptr); |
| 179 | aclrtSetDevice(0); | 202 | aclrtSetDevice(0); |
| 180 | float* src_device = nullptr; | 203 | float* src_device = nullptr; |
| 181 | - aclrtMalloc(reinterpret_cast<void**>(&src_device), (ELEMENT_COUNT) * sizeof(float), | 204 | + aclrtMalloc(reinterpret_cast<void**>(&src_device), (TOTAL_LENGTH) * sizeof(float), |
| 182 | ACL_MEM_MALLOC_HUGE_FIRST); | 205 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 183 | float* dst_device = nullptr; | 206 | float* dst_device = nullptr; |
| 184 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 207 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(float), |
| 185 | ACL_MEM_MALLOC_HUGE_FIRST); | 208 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 186 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), | 209 | aclrtMemcpy(src_device, src.size() * sizeof(float), src.data(), src.size() * sizeof(float), |
| 187 | ACL_MEMCPY_HOST_TO_DEVICE); | 210 | ACL_MEMCPY_HOST_TO_DEVICE); |
| @@ -180,9 +180,12 @@ bisheng example.asc -o main --npu-arch=dav-3510 && ./main | |||
| 180 | #include <vector> | 180 | #include <vector> |
| 181 | 181 | ||
| 182 | #include "c_api/asc_simd.h" | 182 | #include "c_api/asc_simd.h" |
| 183 | +#include "utils/std/cmath.h" | ||
| 183 | #include "acl/acl.h" | 184 | #include "acl/acl.h" |
| 184 | 185 | ||
| 185 | namespace { | 186 | namespace { |
| 187 | +constexpr uint8_t MUTEX_ID = 0; | ||
| 188 | + | ||
| 186 | template <typename T> | 189 | template <typename T> |
| 187 | void print_data(const char* label, const std::vector<T>& values) | 190 | void print_data(const char* label, const std::vector<T>& values) |
| 188 | { | 191 | { |
| @@ -199,36 +202,54 @@ bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected) | |||
| 199 | return actual == expected; | 202 | return actual == expected; |
| 200 | } | 203 | } |
| 201 | 204 | ||
| 202 | -constexpr uint32_t ELEMENT_COUNT = 64; | 205 | +constexpr uint32_t ELEMENTS_PER_REGISTER = 64; |
| 206 | +constexpr uint32_t DATA_BYTES = 137 * sizeof(int32_t); | ||
| 207 | +// 统一记录实际处理长度,用于计算迭代次数并限制尾轮的有效范围。 | ||
| 208 | +constexpr uint32_t TOTAL_LENGTH = DATA_BYTES / sizeof(int32_t); | ||
| 209 | +// 按单轮处理能力向上取整,确保非整寄存器长度的尾块也被处理。 | ||
| 210 | +constexpr uint32_t REPEAT_COUNT = | ||
| 211 | + (TOTAL_LENGTH + ELEMENTS_PER_REGISTER - 1) / ELEMENTS_PER_REGISTER; | ||
| 212 | +// 按完整寄存器块扩展UB容量,避免尾轮整寄存器访问越界;有效范围仍由掩码控制。 | ||
| 213 | +constexpr uint32_t PADDED_ELEMENT_COUNT = REPEAT_COUNT * ELEMENTS_PER_REGISTER; | ||
| 203 | 214 | ||
| 204 | -__simd_vf__ inline void sub_vf(__ubuf__ float* dst, __ubuf__ float* src0, __ubuf__ float* src1) | 215 | +__simd_vf__ inline void sub_vf(__ubuf__ int32_t* dst, __ubuf__ int32_t* src0, __ubuf__ int32_t* src1, uint32_t one_repeat_size, uint16_t repeat_time) |
| 205 | { | 216 | { |
| 206 | - vector_float dst_reg; | 217 | + vector_int32_t dst_reg; |
| 207 | - vector_float src0_reg; | 218 | + vector_int32_t src0_reg; |
| 208 | - vector_float src1_reg; | 219 | + vector_int32_t src1_reg; |
| 209 | - uint32_t count = ELEMENT_COUNT; | 220 | + // 保留剩余有效元素数,供更新掩码处理尾块。 |
| 210 | - vector_bool mask = asc_update_mask_b32(count); | 221 | + uint32_t remaining_length = TOTAL_LENGTH; |
| 211 | - asc_loadalign(src0_reg, src0); | 222 | + for (uint16_t i = 0; i < repeat_time; ++i) { |
| 212 | - asc_loadalign(src1_reg, src1); | 223 | + const uint32_t offset = i * one_repeat_size; |
| 213 | - asc_sub(dst_reg, src0_reg, src1_reg, mask); | 224 | + vector_bool mask = asc_update_mask_b32(remaining_length); |
| 214 | - asc_storealign(dst, dst_reg, mask); | 225 | + asc_loadalign(src0_reg, src0 + offset); |
| 226 | + asc_loadalign(src1_reg, src1 + offset); | ||
| 227 | + asc_sub(dst_reg, src0_reg, src1_reg, mask); | ||
| 228 | + asc_storealign(dst + offset, dst_reg, mask); | ||
| 229 | + } | ||
| 215 | } | 230 | } |
| 216 | 231 | ||
| 217 | -__global__ __vector__ void asc_sub_kernel(__gm__ float* dst, __gm__ float* src0, __gm__ float* src1) | 232 | +__global__ __vector__ void asc_sub_kernel(__gm__ int32_t* dst, __gm__ int32_t* src0, __gm__ int32_t* src1) |
| 218 | { | 233 | { |
| 219 | asc_init(); | 234 | asc_init(); |
| 220 | - __ubuf__ float dst_local[ELEMENT_COUNT]; | 235 | + __ubuf__ int32_t dst_local[PADDED_ELEMENT_COUNT]; |
| 221 | - __ubuf__ float src0_local[ELEMENT_COUNT]; | 236 | + __ubuf__ int32_t src0_local[PADDED_ELEMENT_COUNT]; |
| 222 | - __ubuf__ float src1_local[ELEMENT_COUNT]; | 237 | + __ubuf__ int32_t src1_local[PADDED_ELEMENT_COUNT]; |
| 223 | 238 | ||
| 224 | - asc_copy_gm2ub_align(src0_local, src0, ELEMENT_COUNT * sizeof(float)); | 239 | + asc_lock(PIPE_MTE2, MUTEX_ID); |
| 225 | - asc_copy_gm2ub_align(src1_local, src1, ELEMENT_COUNT * sizeof(float)); | 240 | + asc_copy_gm2ub_align(src0_local, src0, TOTAL_LENGTH * sizeof(int32_t)); |
| 226 | - asc_sync_notify(PIPE_MTE2, PIPE_V, EVENT_ID0); | 241 | + asc_copy_gm2ub_align(src1_local, src1, TOTAL_LENGTH * sizeof(int32_t)); |
| 227 | - asc_sync_wait(PIPE_MTE2, PIPE_V, EVENT_ID0); | 242 | + asc_unlock(PIPE_MTE2, MUTEX_ID); |
| 228 | - sub_vf(dst_local, src0_local, src1_local); | 243 | + |
| 229 | - asc_sync_notify(PIPE_V, PIPE_MTE3, EVENT_ID0); | 244 | + uint32_t one_repeat_size = static_cast<uint32_t>(asc_get_vf_len() / sizeof(int32_t)); |
| 230 | - asc_sync_wait(PIPE_V, PIPE_MTE3, EVENT_ID0); | 245 | + uint16_t repeat_time = static_cast<uint16_t>(AscendC::Std::ceil_div(TOTAL_LENGTH, one_repeat_size)); |
| 231 | - asc_copy_ub2gm_align(dst, dst_local, ELEMENT_COUNT * sizeof(float)); | 246 | + asc_lock(PIPE_V, MUTEX_ID); |
| 247 | + asc_vf_call<sub_vf>(dst_local, src0_local, src1_local, one_repeat_size, repeat_time); | ||
| 248 | + asc_unlock(PIPE_V, MUTEX_ID); | ||
| 249 | + | ||
| 250 | + asc_lock(PIPE_MTE3, MUTEX_ID); | ||
| 251 | + asc_copy_ub2gm_align(dst, dst_local, TOTAL_LENGTH * sizeof(int32_t)); | ||
| 252 | + asc_unlock(PIPE_MTE3, MUTEX_ID); | ||
| 232 | asc_sync(); | 253 | asc_sync(); |
| 233 | } | 254 | } |
| 234 | 255 | ||
| @@ -236,36 +257,36 @@ __global__ __vector__ void asc_sub_kernel(__gm__ float* dst, __gm__ float* src0, | |||
| 236 | 257 | ||
| 237 | int main() | 258 | int main() |
| 238 | { | 259 | { |
| 239 | - std::vector<float> src0(ELEMENT_COUNT); | 260 | + std::vector<int32_t> src0(TOTAL_LENGTH); |
| 240 | - std::vector<float> src1(ELEMENT_COUNT); | 261 | + std::vector<int32_t> src1(TOTAL_LENGTH); |
| 241 | - std::vector<float> output(ELEMENT_COUNT, 0.0f); | 262 | + std::vector<int32_t> output(TOTAL_LENGTH, 0); |
| 242 | - std::vector<float> golden(ELEMENT_COUNT); | 263 | + std::vector<int32_t> golden(TOTAL_LENGTH); |
| 243 | 264 | ||
| 244 | - for (uint32_t i = 0; i < ELEMENT_COUNT; ++i) { | 265 | + for (uint32_t i = 0; i < TOTAL_LENGTH; ++i) { |
| 245 | - src0[i] = static_cast<float>(i) * 0.5f; | 266 | + src0[i] = static_cast<int32_t>(i) - 64; |
| 246 | - src1[i] = static_cast<float>(ELEMENT_COUNT - i) * 0.25f; | 267 | + src1[i] = static_cast<int32_t>(TOTAL_LENGTH - i); |
| 247 | golden[i] = src0[i] - src1[i]; | 268 | golden[i] = src0[i] - src1[i]; |
| 248 | } | 269 | } |
| 249 | 270 | ||
| 250 | aclInit(nullptr); | 271 | aclInit(nullptr); |
| 251 | aclrtSetDevice(0); | 272 | aclrtSetDevice(0); |
| 252 | - float* src0_device = nullptr; | 273 | + int32_t* src0_device = nullptr; |
| 253 | - aclrtMalloc(reinterpret_cast<void**>(&src0_device), (ELEMENT_COUNT) * sizeof(float), | 274 | + aclrtMalloc(reinterpret_cast<void**>(&src0_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 254 | ACL_MEM_MALLOC_HUGE_FIRST); | 275 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 255 | - float* src1_device = nullptr; | 276 | + int32_t* src1_device = nullptr; |
| 256 | - aclrtMalloc(reinterpret_cast<void**>(&src1_device), (ELEMENT_COUNT) * sizeof(float), | 277 | + aclrtMalloc(reinterpret_cast<void**>(&src1_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 257 | ACL_MEM_MALLOC_HUGE_FIRST); | 278 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 258 | - float* dst_device = nullptr; | 279 | + int32_t* dst_device = nullptr; |
| 259 | - aclrtMalloc(reinterpret_cast<void**>(&dst_device), (ELEMENT_COUNT) * sizeof(float), | 280 | + aclrtMalloc(reinterpret_cast<void**>(&dst_device), (TOTAL_LENGTH) * sizeof(int32_t), |
| 260 | ACL_MEM_MALLOC_HUGE_FIRST); | 281 | ACL_MEM_MALLOC_HUGE_FIRST); |
| 261 | - aclrtMemcpy(src0_device, src0.size() * sizeof(float), src0.data(), src0.size() * sizeof(float), | 282 | + aclrtMemcpy(src0_device, src0.size() * sizeof(int32_t), src0.data(), src0.size() * sizeof(int32_t), |
| 262 | ACL_MEMCPY_HOST_TO_DEVICE); | 283 | ACL_MEMCPY_HOST_TO_DEVICE); |
| 263 | - aclrtMemcpy(src1_device, src1.size() * sizeof(float), src1.data(), src1.size() * sizeof(float), | 284 | + aclrtMemcpy(src1_device, src1.size() * sizeof(int32_t), src1.data(), src1.size() * sizeof(int32_t), |
| 264 | ACL_MEMCPY_HOST_TO_DEVICE); | 285 | ACL_MEMCPY_HOST_TO_DEVICE); |
| 265 | 286 | ||
| 266 | asc_sub_kernel<<<1, 0>>>(dst_device, src0_device, src1_device); | 287 | asc_sub_kernel<<<1, 0>>>(dst_device, src0_device, src1_device); |
| 267 | aclrtSynchronizeDevice(); | 288 | aclrtSynchronizeDevice(); |
| 268 | - aclrtMemcpy(output.data(), output.size() * sizeof(float), dst_device, output.size() * sizeof(float), | 289 | + aclrtMemcpy(output.data(), output.size() * sizeof(int32_t), dst_device, output.size() * sizeof(int32_t), |
| 269 | ACL_MEMCPY_DEVICE_TO_HOST); | 290 | ACL_MEMCPY_DEVICE_TO_HOST); |
| 270 | 291 | ||
| 271 | print_data("Input src0", src0); | 292 | print_data("Input src0", src0); |


AscendC::Std::ceil_div可以用,但是要确认下9.2.0商用版本是否支持。