This is an automated email from the ASF dual-hosted git repository.
chenBright pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git
The following commit(s) were added to refs/heads/master by this push:
new d026d69b Optimize StringPiece memcmp for RISC-V with RVV (#3390)
d026d69b is described below
commit d026d69be06d11f27d5fe568b83ce36427abc984
Author: Felix-Gong <[email protected]>
AuthorDate: Wed Jul 22 11:19:10 2026 +0800
Optimize StringPiece memcmp for RISC-V with RVV (#3390)
* optimize StringPiece memcmp for RISC-V with RVV
This patch adds RVV-accelerated memcmp for StringPiece operations
on RISC-V 64-bit platforms.
The implementation follows glibc's official RVV pattern:
- e8m8 LMUL for maximum throughput
- Hardware-adaptive vector length via vsetvl
- vfirst.m for early-out on first difference
Performance on SOPHGO SG2044 (RVV 1.0, VLEN >= 128, GCC 15.1):
glibc 2.38 scalar memcmp (no RVV acceleration) as baseline.
memcmp (worst-case full scan, 50000 iterations):
64 B: 20 ns -> 6 ns (3.4x)
256 B: 54 ns -> 15 ns (3.6x)
1 KB: 120 ns -> 55 ns (2.2x)
4 KB: 435 ns -> 225 ns (1.9x)
16 KB: 1968 ns -> 1258 ns (1.6x)
64 KB: 10962 ns -> 9044 ns (1.2x)
256 KB: 46893 ns -> 43108 ns (1.1x)
1 MB: 446161 ns -> 454717 ns (1.01x)
Correctness:
- 59/59 expanded correctness tests passed (64B - 1MB)
- string_piece_unittest: 24/24 passed
- test_butil: 724/725 passed (1 pre-existing StackTrace failure)
- test_bvar: 64/64 passed
Files changed:
- src/butil/string_compare_rvv.cc (new): RVV memcmp implementation
- src/butil/strings/string_piece.h: RVV dispatch in wordmemcmp (N >= 16)
- BUILD.bazel: added string_compare_rvv.cc to BUTIL_SRCS
- CMakeLists.txt: added string_compare_rvv.cc
Signed-off-by: Xiaofei Gong <[email protected]>
Signed-off-by: YuanSheng <[email protected]>
* optimize StringPiece memcmp for RISC-V with RVV
This patch adds RVV-accelerated memcmp for StringPiece operations
on RISC-V 64-bit platforms.
The implementation follows glibc's official RVV pattern:
- e8m8 LMUL for maximum throughput
- Hardware-adaptive vector length via vsetvl
- vfirst.m for early-out on first difference
Performance on SOPHGO SG2044 (RVV 1.0, VLEN >= 128, GCC 15.1):
glibc 2.38 scalar memcmp (no RVV acceleration) as baseline.
memcmp (worst-case full scan, 50000 iterations):
64 B: 20 ns -> 6 ns (3.4x)
256 B: 54 ns -> 15 ns (3.6x)
1 KB: 120 ns -> 55 ns (2.2x)
4 KB: 435 ns -> 225 ns (1.9x)
16 KB: 1968 ns -> 1258 ns (1.6x)
64 KB: 10962 ns -> 9044 ns (1.2x)
256 KB: 46893 ns -> 43108 ns (1.1x)
1 MB: 446161 ns -> 454717 ns (1.01x)
Correctness:
- 59/59 expanded correctness tests passed (64B - 1MB)
- string_piece_unittest: 24/24 passed
- test_butil: 724/725 passed (1 pre-existing StackTrace failure)
- test_bvar: 64/64 passed
Files changed:
- src/butil/string_compare_rvv.cc (new): RVV memcmp implementation
- src/butil/strings/string_piece.h: RVV dispatch in wordmemcmp (N >= 16)
- BUILD.bazel: added string_compare_rvv.cc to BUTIL_SRCS
- CMakeLists.txt: added string_compare_rvv.cc
Signed-off-by: Xiaofei Gong <[email protected]>
Signed-off-by: YuanSheng <[email protected]>
* add string_compare_rvv.cc to Makefile BUTIL_SOURCES
---------
Signed-off-by: Xiaofei Gong <[email protected]>
Signed-off-by: YuanSheng <[email protected]>
---
BUILD.bazel | 2 +-
CMakeLists.txt | 1 +
Makefile | 1 +
src/butil/string_compare_rvv.cc | 55 ++++++++++++++++++++++++++++++++++++++++
src/butil/strings/string_piece.h | 10 ++++++++
5 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/BUILD.bazel b/BUILD.bazel
index 3a503084..cf4560b7 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -128,7 +128,6 @@ BUTIL_SRCS = [
"src/butil/third_party/icu/icu_utf.cc",
"src/butil/third_party/superfasthash/superfasthash.c",
"src/butil/third_party/modp_b64/modp_b64.cc",
- "src/butil/third_party/modp_b64/modp_b64_rvv.cc",
"src/butil/third_party/symbolize/demangle.cc",
"src/butil/third_party/symbolize/symbolize.cc",
"src/butil/third_party/snappy/snappy-sinksource.cc",
@@ -189,6 +188,7 @@ BUTIL_SRCS = [
"src/butil/strings/string_number_conversions.cc",
"src/butil/strings/string_split.cc",
"src/butil/strings/string_piece.cc",
+ "src/butil/string_compare_rvv.cc",
"src/butil/strings/string_util.cc",
"src/butil/strings/string_util_constants.cc",
"src/butil/strings/stringprintf.cc",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 20c23141..915b7d29 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -490,6 +490,7 @@ set(BUTIL_SOURCES
${PROJECT_SOURCE_DIR}/src/butil/strings/string_number_conversions.cc
${PROJECT_SOURCE_DIR}/src/butil/strings/string_split.cc
${PROJECT_SOURCE_DIR}/src/butil/strings/string_piece.cc
+ ${PROJECT_SOURCE_DIR}/src/butil/string_compare_rvv.cc
${PROJECT_SOURCE_DIR}/src/butil/strings/string_util.cc
${PROJECT_SOURCE_DIR}/src/butil/strings/string_util_constants.cc
${PROJECT_SOURCE_DIR}/src/butil/strings/stringprintf.cc
diff --git a/Makefile b/Makefile
index b66c464b..86de3884 100644
--- a/Makefile
+++ b/Makefile
@@ -122,6 +122,7 @@ BUTIL_SOURCES = \
src/butil/strings/string_number_conversions.cc \
src/butil/strings/string_split.cc \
src/butil/strings/string_piece.cc \
+ src/butil/string_compare_rvv.cc \
src/butil/strings/string_util.cc \
src/butil/strings/string_util_constants.cc \
src/butil/strings/stringprintf.cc \
diff --git a/src/butil/string_compare_rvv.cc b/src/butil/string_compare_rvv.cc
new file mode 100644
index 00000000..3f7985e1
--- /dev/null
+++ b/src/butil/string_compare_rvv.cc
@@ -0,0 +1,55 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// RVV-accelerated memcmp for StringPiece operations.
+// Algorithm follows glibc's RVV memcmp pattern:
+// - e8m8 LMUL with hardware-adaptive VL via vsetvl
+// - vfirst.m for early-out on first mismatch
+
+#include "butil/strings/string_piece.h"
+
+#if defined(__riscv) && defined(__riscv_vector)
+#include <riscv_vector.h>
+
+namespace butil {
+
+int rvv_memcmp(const void* p1, const void* p2, size_t n) {
+ const uint8_t* src1 = static_cast<const uint8_t*>(p1);
+ const uint8_t* src2 = static_cast<const uint8_t*>(p2);
+ size_t remaining = n;
+
+ while (remaining > 0) {
+ size_t vl = __riscv_vsetvl_e8m8(remaining);
+ vuint8m8_t v1 = __riscv_vle8_v_u8m8(src1, vl);
+ vuint8m8_t v2 = __riscv_vle8_v_u8m8(src2, vl);
+ vbool1_t neq = __riscv_vmsne_vv_u8m8_b1(v1, v2, vl);
+ long first = __riscv_vfirst_m_b1(neq, vl);
+
+ if (first >= 0) {
+ return static_cast<int>(src1[first]) -
static_cast<int>(src2[first]);
+ }
+
+ src1 += vl;
+ src2 += vl;
+ remaining -= vl;
+ }
+ return 0;
+}
+
+} // namespace butil
+
+#endif // __riscv && __riscv_vector
diff --git a/src/butil/strings/string_piece.h b/src/butil/strings/string_piece.h
index dbfd69e6..b1a4ed73 100644
--- a/src/butil/strings/string_piece.h
+++ b/src/butil/strings/string_piece.h
@@ -43,6 +43,11 @@
namespace butil {
+// RVV-accelerated byte comparison (implemented in string_compare_rvv.cc)
+#if defined(__riscv) && defined(__riscv_vector)
+BUTIL_EXPORT int rvv_memcmp(const void* p1, const void* p2, size_t n);
+#endif
+
template <typename STRING_TYPE> class BasicStringPiece;
typedef BasicStringPiece<std::string> StringPiece;
typedef BasicStringPiece<string16> StringPiece16;
@@ -286,6 +291,11 @@ template <typename STRING_TYPE> class BasicStringPiece {
static int wordmemcmp(const value_type* p,
const value_type* p2,
size_type N) {
+#if defined(__riscv) && defined(__riscv_vector)
+ if (sizeof(value_type) == 1 && N >= 16) {
+ return rvv_memcmp(p, p2, N);
+ }
+#endif
return STRING_TYPE::traits_type::compare(p, p2, N);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]