Merge remote-tracking branch 'origin/cpx_rotate_aarch64' into integration_2025_w36 (!3613)
Speedup complex rotate for aarch64 This is a simple optimization for aarch64 for the "rotate_cpx_vector" used for the phase_rotation in 5G NR. It provides a speedup of around 1.5 on high-end aarch64 targets compared to the SIMDe translated version. It is implemented with native NEON intrinsics and was largely inspired by suggestions from ChatGPT 5 :-)
This commit is contained in:
+1
-1
@@ -170,7 +170,7 @@ endif()
|
||||
if (NOT CROSS_COMPILE)
|
||||
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=native")
|
||||
else ()
|
||||
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=armv8-a")
|
||||
set(C_FLAGS_PROCESSOR "${C_FLAGS_PROCESSOR} -march=armv8.2-a")
|
||||
endif()
|
||||
|
||||
# add autotools definitions that were maybe used!
|
||||
|
||||
@@ -37,20 +37,11 @@ RUN /bin/sh oaienv && \
|
||||
mkdir -p log ran_build/build ran_build/build-cross && \
|
||||
cd ran_build/build && \
|
||||
cmake ../../.. -GNinja && \
|
||||
echo "====== Start of log for host-tools ======" && \
|
||||
ninja ldpc_generators generate_T > ../../log/host-tools.txt 2>&1 && \
|
||||
echo "====== End of log for host-tools ======" && \
|
||||
ninja ldpc_generators generate_T && \
|
||||
cd ../build-cross/ && \
|
||||
# install missing libyaml-cpp-dev for arm64
|
||||
apt install -y libyaml-cpp-dev:arm64 && \
|
||||
cmake ../../.. -GNinja -DENABLE_TELNETSRV=ON \
|
||||
-DCMAKE_TOOLCHAIN_FILE=../../../cmake_targets/cross-arm.cmake -DNATIVE_DIR=../build \
|
||||
-DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror" && \
|
||||
echo "====== Start of log for cross-build executables ======" && \
|
||||
# making always passing so we can analyze the all.txt file
|
||||
ninja -k10 dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim lte-softmodem nr-softmodem nr-cuup oairu lte-uesoftmodem nr-uesoftmodem params_libconfig coding rfsimulator telnetsrv > ../../log/all.txt 2>&1; \
|
||||
# displaying errors and warnings
|
||||
grep -E -A3 "warning:|error:" ../../log/all.txt || true && \
|
||||
# will fail only if string "errors:" is found
|
||||
grep -E "error:" -vqz ../../log/all.txt && \
|
||||
echo "====== End of log for cross-build executables ======"
|
||||
ninja -k10 dlsim ulsim ldpctest polartest smallblocktest nr_pbchsim nr_dlschsim nr_ulschsim nr_dlsim nr_ulsim nr_pucchsim nr_prachsim lte-softmodem nr-softmodem nr-cuup oairu lte-uesoftmodem nr-uesoftmodem params_libconfig coding rfsimulator telnetsrv
|
||||
|
||||
@@ -828,6 +828,47 @@ static inline void rotate_cpx_vector(const c16_t *const x, const c16_t *const al
|
||||
// log2_amp - increase the output amplitude by a factor 2^log2_amp (default is 0)
|
||||
// WARNING: log2_amp>0 can cause overflow!!
|
||||
|
||||
|
||||
#ifdef __aarch64__
|
||||
if (output_shift == 15) { // allows specific NEON instruction
|
||||
|
||||
int16x8_t ar = (int16x8_t)vdupq_n_s16(alpha->r);
|
||||
int16x8_t ai = (int16x8_t)vdupq_n_s16(alpha->i);
|
||||
int16x8_t *y_128 = (int16x8_t *)y;
|
||||
int16x8_t *x_128 = (int16x8_t *)x;
|
||||
for (uint32_t i = 0; i < (N >> 2); i++) {
|
||||
// Split interleaved -> separate real/imag
|
||||
int16x8_t br = vuzp1q_s16(x_128[i], x_128[i]);
|
||||
int16x8_t bi = vuzp2q_s16(x_128[i], x_128[i]);
|
||||
|
||||
// Start with the two “diagonal” products using high-half, doubling, sat:
|
||||
// x = round( (2*ar*br) / 2^16 ), y = round( (2*ar*bi) / 2^16 )
|
||||
int16x8_t real = vqdmulhq_s16(ar, br);
|
||||
int16x8_t imag = vqdmulhq_s16(ar, bi);
|
||||
|
||||
// real -= round( (2*ai*bi) / 2^16 )
|
||||
real = vqrdmlshq_s16(real, ai, bi);
|
||||
|
||||
// imag += round( (2*ai*br) / 2^16 )
|
||||
imag = vqrdmlahq_s16(imag, ai, br);
|
||||
|
||||
// Re-interleave [real, imag]
|
||||
int16x8x2_t z = vzipq_s16(real, imag);
|
||||
|
||||
y_128[i] = z.val[0];
|
||||
/*
|
||||
printf("y : (%d %d) (%d %d) (%d %d) (%d %d)\n",
|
||||
vgetq_lane_s16(y_128[i],0),
|
||||
vgetq_lane_s16(y_128[i],1),
|
||||
vgetq_lane_s16(y_128[i],2),
|
||||
vgetq_lane_s16(y_128[i],3),
|
||||
vgetq_lane_s16(y_128[i],4),
|
||||
vgetq_lane_s16(y_128[i],5),
|
||||
vgetq_lane_s16(y_128[i],6),
|
||||
vgetq_lane_s16(y_128[i],7));*/
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
uint32_t i; // loop counter
|
||||
|
||||
simd_q15_t *y_128, alpha_128;
|
||||
@@ -859,7 +900,10 @@ static inline void rotate_cpx_vector(const c16_t *const x, const c16_t *const al
|
||||
shift));
|
||||
// print_ints("y_128[0]=", &y_128[0]);
|
||||
}
|
||||
#if defined(__x86__) || defined(__x86_64__)
|
||||
#ifdef __aarch64__
|
||||
}
|
||||
#endif //__aarch64__
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user