已合并
docs: 优化C API调用示例的同步、VF循环及变量命名 #6846
docs: 优化C API调用示例的同步、VF循环及变量命名 #6846
已合并
GRJ_XIDUO创建于 16 天前
共 279 个文件变更+9390-5067
@@ -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```cpp110```cpp
111template<typename T>111template<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 
183bool CheckResult(const std::vector<float>& matmul_result, const std::vector<float>& output)183bool 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 
361template <typename T>361template <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 
285void print_row(const char* label, const std::vector<float>& data)285void 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 
126void print_row(const char* label, const std::vector<float>& data)126void 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 
133void print_row(const char* label, const std::vector<float>& data)133void 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 
188void print_row(const char* label, const std::vector<float>& data)188void 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 
114void print_row(const char* label, const std::vector<float>& data)114void 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 
118void print_row(const char* label, const std::vector<float>& data)118void 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 
120void print_row(const char* label, const std::vector<int32_t>& data)120void 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 
119void print_row(const char* label, const std::vector<int32_t>& data)119void 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 
183uint16_t ToHalfBits(int32_t value)183uint16_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 
250std::vector<uint8_t> MakeInput()250std::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 
169uint16_t ToHalfBits(int32_t value)169uint16_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 
164int main()164int 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} // namespace249} // 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} // namespace243} // 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} // namespace122} // 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 
137bool IsGolden(const std::vector<uint8_t>& output)137bool 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 
155void print_row(const char* label, const std::vector<float>& data)155void 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} // namespace144} // 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 
196size_t FmapIndex(uint32_t n, uint32_t h, uint32_t w, uint32_t c)196size_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} // namespace159} // 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 
185size_t fmap_index(uint32_t n, uint32_t h, uint32_t w, uint32_t c)185size_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} // namespace159} // 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 
184size_t fmap_index(uint32_t n, uint32_t h, uint32_t w, uint32_t c)184size_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} // namespace154} // 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} // namespace159} // 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 
128void print_row(const char* label, const std::vector<float>& data, uint32_t offset)128void 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 
157void print_row(const char* label, const std::vector<int8_t>& data)157void 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 
125void print_row(const char* label, const std::vector<uint16_t>& data)125void 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 
120void print_row(const char* label, const std::vector<float>& data)120void 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 
208void print_row(const char* label, const std::vector<int8_t>& data)208void 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 
128void print_row(const char* label, const std::vector<uint16_t>& data)128void 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 
203uint16_t ToHalfBits(int32_t value)203uint16_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 
270std::vector<uint8_t> MakeInput()270std::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 
243std::vector<uint8_t> MakeInput()243std::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 
173uint16_t ToHalfBits(int32_t value)173uint16_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 
179uint16_t ToHalfBits(int32_t value)179uint16_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 
170uint16_t ToHalfBits(int32_t value)170uint16_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} // namespace226} // 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 
117void print_row(const char* label, const std::vector<float>& data)117void 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 
121void print_row(const char* label, const std::vector<float>& data)121void 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 
136void print_row(const char* label, const std::vector<float>& data, uint32_t offset)136void 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 
121void print_row(const char* label, const std::vector<float>& data)121void 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 
106namespace {107namespace {
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;
114constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);112constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);
115constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);113constexpr 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} // namespace155} // 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"
258namespace {259namespace {
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 
264template <typename T>262template <typename T>
265void print_data(const char* label, const std::vector<T>& values)263void 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;
GRJ_XIDUO
GRJ_XIDUOGRJ_XIDUO14 天前

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

likedislike
GRJ_XIDUO
GRJ_XIDUO
14 天前 评论:
275constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t);276constexpr 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} // namespace316} // 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 
177namespace {178namespace {
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;
185constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);183constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);
186constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);184constexpr 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} // namespace228} // 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 
102namespace {103namespace {
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;
110constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);108constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);
111constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);109constexpr 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} // namespace154} // 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 
181namespace {182namespace {
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;
189constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);189constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);
190constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);190constexpr 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);
atomgit-bot
atomgit-botatomgit-bot16 天前

🟡 Medium Priority

变更链:本 diff 把 kernel 中的 UB 数组声明由 __ubuf__ uint8_t input_local[INPUT_ELEMENTS](=517字节)改成 input_local[INPUT_STORAGE_ELEMENTS],其中新增的 INPUT_STORAGE_ELEMENTS = REPEAT_COUNT * 1(REPEAT_COUNT = ceil_division(517,256) = 3)→ 只有 3 字节;但紧随其后的搬入语句 asc_copy_gm2ub_align(input_local, input, INPUT_BYTES) 仍然使用未改动的 INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t) = 517。\n\n失效模式:UB 上仅 3 字节的栈数组被写入 517 字节,越界 514 字节,会覆盖 UB 栈帧中相邻的 output_local 等数据(或触发 UB 栈越界),示例结果不可预期;该文档是给用户直接拷贝的调用示例,用户照抄即得缓冲区溢出代码。\n\n旁证(同一 PR 内的不一致):其姊妹文档 asc_loadalign_brc_elem_postupdate.md 对同一接口正确地写成 INPUT_ELEMENTS = ceil_division(OUTPUT_ELEMENTS, 256)(=3)、INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t)(=3),与本文件的 517 取值矛盾,说明本文件是漏改。\n\n注:vf 实际每轮只读取 input + i(i=0..2,共 3 个元素),因此 3 才是正确的读取规模,517 的搬入尺寸是关键错误。

建议:将搬入尺寸改为与 UB 缓冲区一致:把 kernel 中 asc_copy_gm2ub_align(input_local, input, INPUT_BYTES) 的尺寸替换为 INPUT_STORAGE_ELEMENTS;或与姊妹文档 asc_loadalign_brc_elem_postupdate.md 对齐,把定义改为 INPUT_ELEMENTS = ceil_division(OUTPUT_ELEMENTS, ELEMENTS_PER_REGISTER)(=3)并令 INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t)。同时确认宿主侧 input 向量与 aclrtMalloc 的尺寸仍按需保留 517。

likedislike
不准确?
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} // namespace230} // 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 
177namespace {178namespace {
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;
185constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint16_t);183constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint16_t);
186constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint16_t);184constexpr 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} // namespace228} // 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 
100namespace {101namespace {
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;
108constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint16_t);106constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint16_t);
109constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint16_t);107constexpr 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} // namespace152} // 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 
106namespace {107namespace {
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);
114constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);112constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);
115constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);113constexpr 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} // namespace158} // 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 
103namespace {104namespace {
105+ 
104constexpr uint32_t DATABLOCK_BYTES = 32;106constexpr 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;
106constexpr uint16_t BLOCK_STRIDE = 2;109constexpr 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} // namespace162} // namespace
@@ -136,14 +164,20 @@ __global__ __vector__ void asc_loadalign_datablock_strided_kernel(
136int main()164int 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 
181namespace {182namespace {
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} // namespace234} // namespace
222 235 
223int main()236int 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 
107namespace {108namespace {
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} // namespace161} // namespace
149 162 
150int main()163int 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 
201namespace {202namespace {
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;
209constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);207constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);
210constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);208constexpr 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} // namespace251} // namespace
240 252 
241int main()253int 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 
112namespace {113namespace {
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;
120constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);118constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);
121constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);119constexpr 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} // namespace164} // namespace
153 165 
154int main()166int 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 
84namespace {85namespace {
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} // namespace133} // namespace
110 134 
111int main()135int 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 
84namespace {85namespace {
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} // namespace138} // namespace
111 139 
112int main()140int 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 
84namespace {85namespace {
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} // namespace140} // namespace
112 141 
113int main()142int 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"
173namespace {174namespace {
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 
179template <typename T>177template <typename T>
180void print_data(const char* label, const std::vector<T>& dst_regs)178void 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;
190constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t);191constexpr 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} // namespace232} // 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 
181namespace {182namespace {
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;
189constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);187constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);
190constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);188constexpr 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} // namespace231} // 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 
177namespace {178namespace {
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);
186constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);183constexpr 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} // namespace227} // namespace
216 228 
217int main()229int 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 
100namespace {101namespace {
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);
109constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);106constexpr 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} // namespace152} // namespace
141 153 
142int main()154int 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 
104namespace {105namespace {
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;
112constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);110constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);
113constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);111constexpr 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} // namespace156} // 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 
201namespace {202namespace {
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;
209constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);207constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);
210constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);208constexpr 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} // namespace251} // 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 
112namespace {113namespace {
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;
120constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);118constexpr uint32_t INPUT_BYTES = INPUT_ELEMENTS * sizeof(uint8_t);
121constexpr uint32_t OUTPUT_BYTES = OUTPUT_ELEMENTS * sizeof(uint8_t);119constexpr 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} // namespace164} // 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 
99namespace {100namespace {
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;
107constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t);108constexpr 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} // namespace150} // 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 
177namespace {178namespace {
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;
185constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t);186constexpr 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} // namespace230} // 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 
168namespace {169namespace {
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;
176constexpr uint32_t BUFFER_BYTES = BUFFER_ELEMENTS * sizeof(uint8_t);177constexpr 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} // namespace220} // 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 
137namespace {138namespace {
139+constexpr uint8_t MUTEX_ID = 0;
140+ 
141+ 
138template <typename T>142template <typename T>
139bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0)143bool 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 
150constexpr uint16_t ONE_REPEAT_SIZE = 256;154constexpr 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;
152constexpr uint32_t TOTAL_BYTES = ONE_REPEAT_SIZE * REPEAT_COUNT;157constexpr 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} // namespace196} // namespace
183 197 
184int main()198int 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 
120namespace {121namespace {
122+constexpr uint8_t MUTEX_ID = 0;
123+ 
121template <typename T>124template <typename T>
122bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0)125bool 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 
163int main()184int 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 
183namespace {184namespace {
@@ -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 
235int main()263int 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 
114namespace {115namespace {
116+constexpr uint8_t MUTEX_ID = 0;
117+ 
115template <typename T>118template <typename T>
116bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0)119bool 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;
128constexpr float SCALAR_VALUE = 2.0f;139constexpr 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 
158int main()179int 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 
123namespace {124namespace {
125+constexpr uint8_t MUTEX_ID = 0;
126+ 
124template <typename T>127template <typename T>
125void print_data(const char* label, const std::vector<T>& values)128void 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;
141constexpr uint32_t CARRY_WORDS = 8;152constexpr 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 
180int main()202int 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 
121namespace {122namespace {
123+constexpr uint8_t MUTEX_ID = 0;
124+ 
122template <typename T>125template <typename T>
123void print_data(const char* label, const std::vector<T>& values)126void 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} // namespace196} // namespace
176 197 
177int main()198int 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```bash98```bash
99bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main99bisheng 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```c105```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 
113namespace {116namespace {
117+constexpr uint8_t MUTEX_ID = 0;
118+ 
114template <typename T>119template <typename T>
115void print_data(const char* label, const std::vector<T>& values)120void 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} // namespace186} // namespace
164 187 
165int main()188int 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```bash89```bash
90bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main90bisheng 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```cpp96```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 
104namespace {107namespace {
108+constexpr uint8_t MUTEX_ID = 0;
109+ 
105template <typename T>110template <typename T>
106bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0)111bool 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 
147int main()170int 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```bash90```bash
91bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main91bisheng 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```cpp97```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 
105namespace {108namespace {
109+constexpr uint8_t MUTEX_ID = 0;
110+ 
106template <typename T>111template <typename T>
107bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0)112bool 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 
148int main()171int 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 
120namespace {121namespace {
122+constexpr uint8_t MUTEX_ID = 0;
123+ 
121template <typename T>124template <typename T>
122void print_data(const char* label, const std::vector<T>& values)125void 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 
177int main()203int 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 
115namespace {116namespace {
117+constexpr uint8_t MUTEX_ID = 0;
118+ 
116template <typename T>119template <typename T>
117bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0)120bool 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;
129constexpr float SCALAR_VALUE = 3.0f;140constexpr 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 
159int main()180int 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 
119namespace {120namespace {
121+constexpr uint8_t MUTEX_ID = 0;
122+ 
120template <typename T>123template <typename T>
121void print_data(const char* label, const std::vector<T>& values)124void 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 
176int main()197int 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 
114namespace {115namespace {
116+constexpr uint8_t MUTEX_ID = 0;
117+ 
115template <typename T>118template <typename T>
116bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0)119bool 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;
128constexpr float SCALAR_VALUE = 3.0f;139constexpr 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 
158int main()179int 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 
119namespace {120namespace {
121+constexpr uint8_t MUTEX_ID = 0;
122+ 
120template <typename T>123template <typename T>
121void print_data(const char* label, const std::vector<T>& values)124void 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 
176int main()197int 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 
113namespace {114namespace {
115+constexpr uint8_t MUTEX_ID = 0;
116+ 
114template <typename T>117template <typename T>
115bool compare_data(const std::vector<T>& actual, const std::vector<T>& expected, double tolerance = 0.0)118bool 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;
127constexpr float SCALAR_VALUE = 2.0f;138constexpr 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 
157int main()178int 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 
123namespace {124namespace {
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} // namespace187} // namespace
166 188 
167int main()189int 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 
116namespace {117namespace {
118+constexpr uint8_t MUTEX_ID = 0;
119+ 
117template <typename T>120template <typename T>
118void print_data(const char* label, const std::vector<T>& values)121void 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 
169int main()190int 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```bash101```bash
102bisheng example.asc -o main --npu-arch=dav-3510 -lm && ./main102bisheng 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```c108```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 
116namespace {119namespace {
120+constexpr uint8_t MUTEX_ID = 0;
121+ 
117template <typename T>122template <typename T>
118void print_data(const char* label, const std::vector<T>& values)123void 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} // namespace189} // namespace
167 190 
168int main()191int 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 
185namespace {186namespace {
187+constexpr uint8_t MUTEX_ID = 0;
188+ 
186template <typename T>189template <typename T>
187void print_data(const char* label, const std::vector<T>& values)190void 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 
237int main()258int 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);