From c5a47492ff9894998d39d98f2fe5037942485310 Mon Sep 17 00:00:00 2001 From: mfritsche Date: Thu, 9 Jul 2026 00:59:39 +0200 Subject: [PATCH] rknpu2: skip dst memset + RMW when single K-segment Experiment: with one K-segment (K<=8192, the common case) each dst element is written exactly once (N-segments are disjoint), so the full-MxN memset and the read-modify-write accumulate are dead work. Write each element once; keep the +=/memset path for multi-K. Byte-identical output. Throughput ~neutral (NPU-bound, so CPU-side traffic saving is marginal): E1 pp300/pp512/pp700/tg 37.01/40.25/40.03/2.61 -> E2 35.8/41.1/40.3/2.57 (pp512/pp700 +1-2%, pp300 within run variance). Kept for traffic reduction and as prerequisite for E5 NEON collect. --- ggml/src/ggml-rknpu2/ggml-rknpu2.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/ggml/src/ggml-rknpu2/ggml-rknpu2.cpp b/ggml/src/ggml-rknpu2/ggml-rknpu2.cpp index 9abc4b2cb..5a3973d11 100644 --- a/ggml/src/ggml-rknpu2/ggml-rknpu2.cpp +++ b/ggml/src/ggml-rknpu2/ggml-rknpu2.cpp @@ -546,9 +546,15 @@ static enum ggml_status ggml_backend_rknpu_graph_compute(ggml_backend_t backend, b_domain_id = it->second.iommu_domain_id; } - // Cleaning the C-matrix buffer + // Cleaning the C-matrix buffer. + // Accumulation is only real across K-segments; N-segments write disjoint + // N ranges. With a single K-segment each dst element is written exactly + // once, so the zero-fill and the read-modify-write below are dead work. + const bool single_k_segment = (all_k_segments.size() == 1); float* dst_data = (float*)get_tensor_real_ptr(dst); - memset(dst_data, 0, (size_t)M * N * sizeof(float)); + if (!single_k_segment) { + memset(dst_data, 0, (size_t)M * N * sizeof(float)); + } // Acquiring the Hadamard vector std::vector s_vec; @@ -747,8 +753,10 @@ static enum ggml_status ggml_backend_rknpu_graph_compute(ggml_backend_t backend, float* dst_ptr = dst_data + (size_t)m * N + N_offset; float* src_ptr = src_segment_base + (size_t)m * N_segment; - for(int n=0; nvirt_addr + (size_t)m * N_segment; - for(int n=0; nvirt_addr + (size_t)m * N_segment; - for(int n=0; n