Skip to content

Commit aedcd37

Browse files
AWSjswinneypablodelara
authored andcommitted
aarch64: Use NEON when SVE width is 128 bits
On AArch64 systems with SVE support, 128-bit SVE implementations can perform significantly worse than equivalent NEON code due to the different optimization strategies used in each implementation. The NEON version is unrolled 4 times, providing excellent performance at the fixed 128-bit width. The SVE version can achieve similar or better performance through its variable-width operations on systems with 256-bit or 512-bit SVE, but on 128-bit SVE systems, the NEON unrolled implementation is faster due to reduced overhead. This change adds runtime detection of SVE vector length and falls back to the optimized NEON implementation when SVE is operating at 128-bit width, ensuring optimal performance across all AArch64 configurations. This implementation checks the vector length with an intrinsic if the compiler supports it (which works on Apple as well) and falls back to using prctl otherwise. This optimization ensures that systems benefit from: - 4x unrolled NEON code on 128-bit SVE systems - Variable-width SVE optimizations on wider SVE implementations - Maintained compatibility across different AArch64 configurations Performance improvement on systems with 128-bit SVE: - Encode: 7509.80 MB/s → 8995.59 MB/s (+19.8% improvement) - Decode: 9383.67 MB/s → 12272.38 MB/s (+30.8% improvement) Signed-off-by: Jonathan Swinney <[email protected]>
1 parent 09cec64 commit aedcd37

File tree

1 file changed

+43
-1
lines changed

1 file changed

+43
-1
lines changed

erasure_code/aarch64/ec_aarch64_dispatcher.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,40 @@
3030
#include "erasure_code.h"
3131
#include "gf_vect_mul.h"
3232

33+
#ifdef __ARM_FEATURE_SVE
34+
// If the compiler defines SVE intrinsics, include that header
35+
#include <arm_sve.h>
36+
37+
#elif defined(__linux__)
38+
// Otherwise include these headers and define these constants as a fallback for Linux only
39+
#include <stddef.h>
40+
#include <sys/auxv.h>
41+
#include <sys/prctl.h>
42+
#ifndef PR_SVE_GET_VL
43+
#define PR_SVE_GET_VL 51
44+
#endif
45+
#ifndef PR_SVE_VL_LEN_MASK
46+
#define PR_SVE_VL_LEN_MASK 0xffff
47+
#endif
48+
49+
#endif
50+
51+
static inline size_t
52+
get_sve_vector_length_bytes(void)
53+
{
54+
#ifdef __ARM_FEATURE_SVE
55+
// Use intrinsic if available at compile time
56+
return svcntb();
57+
#elif defined(__linux__)
58+
// Fall back to prctl on Linux
59+
long sve_vl = prctl(PR_SVE_GET_VL);
60+
if (sve_vl != -1) {
61+
return sve_vl & PR_SVE_VL_LEN_MASK;
62+
}
63+
#endif
64+
return 0; // Unknown or unavailable
65+
}
66+
3367
extern void
3468
gf_vect_dot_prod_sve(int, int, unsigned char *, unsigned char **, unsigned char *);
3569
extern void
@@ -94,8 +128,16 @@ DEFINE_INTERFACE_DISPATCHER(ec_encode_data)
94128
#if defined(__linux__)
95129
unsigned long auxval = getauxval(AT_HWCAP);
96130

97-
if (auxval & HWCAP_SVE)
131+
if (auxval & HWCAP_SVE) {
132+
size_t vector_length = get_sve_vector_length_bytes();
133+
134+
// If 128-bit SVE (16 bytes), use NEON instead
135+
if (vector_length == 16 && (auxval & HWCAP_ASIMD)) {
136+
return ec_encode_data_neon;
137+
}
138+
98139
return ec_encode_data_sve;
140+
}
99141
if (auxval & HWCAP_ASIMD)
100142
return ec_encode_data_neon;
101143
#elif defined(__APPLE__)

0 commit comments

Comments
 (0)