[PATCH] hash: add riscv vector support for 16-byte key comparison
P1erreCashon
2022302111412 at whu.edu.cn
Thu Feb 26 07:49:38 CET 2026
Add RISC-V Vector (RVV) optimized implementation for
rte_hash_k16_cmp_eq() to accelerate 16-byte key comparison
in hash lookup fast path.
The implementation uses RVV vector load and compare
instructions to detect mismatched bytes and reduces
comparison latency on RVV-capable systems.
This patch is co-developed with gong-flying.
Signed-off-by: gong-flying <gongxiaofei24 at iscas.ac.cn>
Signed-off-by: P1erreCashon <2022302111412 at whu.edu.cn>
---
config/riscv/meson.build | 18 +++++++-
lib/hash/rte_cmp_riscv.h | 93 ++++++++++++++++++++++++++++++++++++++
lib/hash/rte_cuckoo_hash.c | 2 +-
lib/hash/rte_cuckoo_hash.h | 6 ++-
4 files changed, 116 insertions(+), 3 deletions(-)
create mode 100644 lib/hash/rte_cmp_riscv.h
diff --git a/config/riscv/meson.build b/config/riscv/meson.build
index 07d7d9da23..a844faaa7b 100644
--- a/config/riscv/meson.build
+++ b/config/riscv/meson.build
@@ -113,12 +113,28 @@ dpdk_flags = flags_common + vendor_config['flags'] + arch_config.get('flags', []
# apply supported machine args
machine_args = [] # Clear previous machine args
-foreach flag: arch_config['machine_args']
+
+# detect best ISA
+if cc.has_argument('-march=rv64gc_zve64x')
+ machine_args += ['-march=rv64gc_zve64x']
+ dpdk_conf.set('RTE_ARCH_RISCV_VEC', 1)
+ message('Using rv64gc_zve64x')
+else
+ machine_args += ['-march=rv64gc']
+ message('Using rv64gc (fallback)')
+endif
+
+# apply extra tuning flags (like -mtune)
+foreach flag: arch_config.get('machine_args', [])
+ if flag.startswith('-march')
+ continue
+ endif
if cc.has_argument(flag)
machine_args += flag
endif
endforeach
+
# apply flags
foreach flag: dpdk_flags
if flag.length() > 0
diff --git a/lib/hash/rte_cmp_riscv.h b/lib/hash/rte_cmp_riscv.h
new file mode 100644
index 0000000000..7881d17e05
--- /dev/null
+++ b/lib/hash/rte_cmp_riscv.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015 Intel Corporation
+ */
+
+#include <riscv_vector.h>
+
+/* Functions to compare multiple of 16 byte keys (up to 128 bytes) */
+static inline int
+rte_hash_k16_cmp_eq(const void *key1, const void *key2, size_t key_len __rte_unused)
+{
+ const uint8_t *p1 = (const uint8_t *)key1;
+ const uint8_t *p2 = (const uint8_t *)key2;
+ size_t offset = 0;
+
+ while (offset < 16) {
+ size_t vl = __riscv_vsetvl_e8m1(16 - offset);
+
+ vuint8m1_t v1 = __riscv_vle8_v_u8m1(p1 + offset, vl);
+ vuint8m1_t v2 = __riscv_vle8_v_u8m1(p2 + offset, vl);
+
+ /* find != bytes */
+ vbool8_t neq = __riscv_vmsne_vv_u8m1_b8(v1, v2, vl);
+
+ /* if any byte mismatches, return not equal */
+ if (__riscv_vfirst_m_b8(neq, vl) >= 0)
+ return 1;
+
+ offset += vl;
+ }
+
+ /* all bytes equal */
+ return 0;
+}
+
+static inline int
+rte_hash_k32_cmp_eq(const void *key1, const void *key2, size_t key_len)
+{
+ return rte_hash_k16_cmp_eq(key1, key2, key_len) ||
+ rte_hash_k16_cmp_eq((const char *) key1 + 16,
+ (const char *) key2 + 16, key_len);
+}
+
+static inline int
+rte_hash_k48_cmp_eq(const void *key1, const void *key2, size_t key_len)
+{
+ return rte_hash_k16_cmp_eq(key1, key2, key_len) ||
+ rte_hash_k16_cmp_eq((const char *) key1 + 16,
+ (const char *) key2 + 16, key_len) ||
+ rte_hash_k16_cmp_eq((const char *) key1 + 32,
+ (const char *) key2 + 32, key_len);
+}
+
+static inline int
+rte_hash_k64_cmp_eq(const void *key1, const void *key2, size_t key_len)
+{
+ return rte_hash_k32_cmp_eq(key1, key2, key_len) ||
+ rte_hash_k32_cmp_eq((const char *) key1 + 32,
+ (const char *) key2 + 32, key_len);
+}
+
+static inline int
+rte_hash_k80_cmp_eq(const void *key1, const void *key2, size_t key_len)
+{
+ return rte_hash_k64_cmp_eq(key1, key2, key_len) ||
+ rte_hash_k16_cmp_eq((const char *) key1 + 64,
+ (const char *) key2 + 64, key_len);
+}
+
+static inline int
+rte_hash_k96_cmp_eq(const void *key1, const void *key2, size_t key_len)
+{
+ return rte_hash_k64_cmp_eq(key1, key2, key_len) ||
+ rte_hash_k32_cmp_eq((const char *) key1 + 64,
+ (const char *) key2 + 64, key_len);
+}
+
+static inline int
+rte_hash_k112_cmp_eq(const void *key1, const void *key2, size_t key_len)
+{
+ return rte_hash_k64_cmp_eq(key1, key2, key_len) ||
+ rte_hash_k32_cmp_eq((const char *) key1 + 64,
+ (const char *) key2 + 64, key_len) ||
+ rte_hash_k16_cmp_eq((const char *) key1 + 96,
+ (const char *) key2 + 96, key_len);
+}
+
+static inline int
+rte_hash_k128_cmp_eq(const void *key1, const void *key2, size_t key_len)
+{
+ return rte_hash_k64_cmp_eq(key1, key2, key_len) ||
+ rte_hash_k64_cmp_eq((const char *) key1 + 64,
+ (const char *) key2 + 64, key_len);
+}
diff --git a/lib/hash/rte_cuckoo_hash.c b/lib/hash/rte_cuckoo_hash.c
index 9cf94645f6..159001f2fa 100644
--- a/lib/hash/rte_cuckoo_hash.c
+++ b/lib/hash/rte_cuckoo_hash.c
@@ -357,7 +357,7 @@ rte_hash_create(const struct rte_hash_parameters *params)
* If x86 architecture is used, select appropriate compare function,
* which may use x86 intrinsics, otherwise use memcmp
*/
-#if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM64)
+#if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM64) || defined(RTE_ARCH_RISCV_VEC)
/* Select function to compare keys */
switch (params->key_len) {
case 16:
diff --git a/lib/hash/rte_cuckoo_hash.h b/lib/hash/rte_cuckoo_hash.h
index a528f1d1a0..b693abcb89 100644
--- a/lib/hash/rte_cuckoo_hash.h
+++ b/lib/hash/rte_cuckoo_hash.h
@@ -21,6 +21,10 @@
#include "rte_cmp_arm64.h"
#endif
+#if defined(RTE_ARCH_RISCV_VEC)
+#include "rte_cmp_riscv.h"
+#endif
+
/* Macro to enable/disable run-time checking of function parameters */
#if defined(RTE_LIBRTE_HASH_DEBUG)
#define RETURN_IF_TRUE(cond, retval) do { \
@@ -34,7 +38,7 @@
#include <rte_hash_crc.h>
#include <rte_jhash.h>
-#if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM64)
+#if defined(RTE_ARCH_X86) || defined(RTE_ARCH_ARM64) || defined(RTE_ARCH_RISCV_VEC)
/*
* All different options to select a key compare function,
* based on the key size and custom function.
--
2.43.0
More information about the dev
mailing list