Merge branch 'ahmed-moreilp' into 'main'

Ahmed moreilp

See merge request course-asl-fastcode26/team70!76
This commit is contained in:
Linus Baumberger
2026-06-15 13:59:29 +02:00
@@ -175,21 +175,44 @@ Pedestrian *init_pedestrians(int n_p) {
Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); }
// # 64 MULTs, 56 ADDs
static inline float32x4_t _neon_exp_ps(float32x4_t x) {
const float32x4_t log2e = vdupq_n_f32(1.4426950408889634f);
// # 4 MULTS
float32x4_t nf = vrndnq_f32(vmulq_f32(x, log2e));
const float32x4_t ln2 = vdupq_n_f32(0.6931471805599453f);
// # 4 MULTs, 4 ADDs
float32x4_t r = vfmsq_f32(x, nf, ln2); // r = x - nf*ln2
const float32x4_t c5 = vdupq_n_f32(1.0f / 120.0f);
const float32x4_t c4 = vdupq_n_f32(1.0f / 24.0f);
const float32x4_t c3 = vdupq_n_f32(1.0f / 6.0f);
const float32x4_t c2 = vdupq_n_f32(0.5f);
const float32x4_t c1 = vdupq_n_f32(1.0f);
const float32x4_t c0 = vdupq_n_f32(1.0f);
const float32x4_t c12 = vdupq_n_f32(c12_scalar);
const float32x4_t c11 = vdupq_n_f32(c11_scalar);
const float32x4_t c10 = vdupq_n_f32(c10_scalar);
const float32x4_t c9 = vdupq_n_f32(c9_scalar);
const float32x4_t c8 = vdupq_n_f32(c8_scalar);
const float32x4_t c7 = vdupq_n_f32(c7_scalar);
const float32x4_t c6 = vdupq_n_f32(c6_scalar);
const float32x4_t c5 = vdupq_n_f32(c5_scalar);
const float32x4_t c4 = vdupq_n_f32(c4_scalar);
const float32x4_t c3 = vdupq_n_f32(c3_scalar);
const float32x4_t c2 = vdupq_n_f32(c2_scalar);
const float32x4_t c1 = vdupq_n_f32(c1_scalar);
const float32x4_t c0 = vdupq_n_f32(c0_scalar);
float32x4_t p = c5;
float32x4_t p = c12;
// # 13 * (4 MULTs, 4 ADDs)
// # = 52 MULTs, 52 ADDs
p = vfmaq_f32(c12, p, r);
p = vfmaq_f32(c11, p, r);
p = vfmaq_f32(c10, p, r);
p = vfmaq_f32(c9, p, r);
p = vfmaq_f32(c8, p, r);
p = vfmaq_f32(c7, p, r);
p = vfmaq_f32(c6, p, r);
p = vfmaq_f32(c5, p, r);
p = vfmaq_f32(c4, p, r);
p = vfmaq_f32(c3, p, r);
p = vfmaq_f32(c2, p, r);
@@ -201,12 +224,17 @@ static inline float32x4_t _neon_exp_ps(float32x4_t x) {
int32x4_t scaled = vshlq_n_s32(biased, 23);
float32x4_t pow2n = vreinterpretq_f32_s32(scaled);
// # 4 MULTs
return vmulq_f32(p, pow2n);
}
// # 4 ADD, 16 MULTS, 4 SQRT, 4 DIV
// Newton-Raphson refinement formula.
static inline float32x4_t _neon_rsqrt_ps(float32x4_t x) {
// # 4 SQRT, 4 DIV
float32x4_t y = vrsqrteq_f32(x);
// # 16 MULTS, 4 ADD
y = vmulq_f32(y, vrsqrtsq_f32(vmulq_f32(x, y), y));
return y;
}
@@ -244,12 +272,42 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c
const float32x4_t v_np = vdupq_n_f32((float)n_p);
const float32x4_t v_exp_min = vdupq_n_f32(-87.0f);
// # ADDs: n_iter * (
// # n_p * 20 +
// # n_p * n_p_pad * 32 +
// # n_p * board.n_obstacles * 10 +
// # n_p_pad * 9
// # )
// # MULTs: n_iter * (
// # n_p * 4 +
// # n_p * n_p_pad * 54 +
// # n_p * board.n_obstacles * 13 +
// # n_p_pad * 24
// # )
// # DIVs: n_iter * (
// # n_p * n_p_pad * 3 +
// # n_p * board.n_obstacles +
// # n_p_pad * 2
// # )
// # SQRTs: n_iter * (
// # n_p * n_p_pad * 3 +
// # n_p * board.n_obstacles +
// # n_p_pad * 3
// # )
// # EXPs: n_iter * n_p * board.n_obstacles
for (int t = 0; t < n_iter; t++) {
for (int i = 0; i < n_p; i++) {
// # 2 MULTS
float desired_velocity_x = e_x[i] * desired_v0[i];
float desired_velocity_y = e_y[i] * desired_v0[i];
// # 2 ADDS, 2 MULTS
float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv;
float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv;
@@ -266,6 +324,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c
for (int j = 0; j < n_p_pad; j += 8) {
// # 8 ADDS
float32x4_t j_idx_0 = vaddq_f32(vdupq_n_f32((float)j), lane_off);
float32x4_t j_idx_1 = vaddq_f32(vdupq_n_f32((float)(j + 4)), lane_off);
@@ -287,86 +346,107 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c
float32x4_t sb_jsq_0 = vld1q_f32(&sb_sq[j]);
float32x4_t sb_jsq_1 = vld1q_f32(&sb_sq[j + 4]);
// # 16 ADDS
float32x4_t r_ab_x_0 = vsubq_f32(pix, pjx_0);
float32x4_t r_ab_x_1 = vsubq_f32(pix, pjx_1);
float32x4_t r_ab_y_0 = vsubq_f32(piy, pjy_0);
float32x4_t r_ab_y_1 = vsubq_f32(piy, pjy_1);
// # 8 ADDS, 16 MULTS
float32x4_t r_ab_n2_0 = vfmaq_f32(vmulq_f32(r_ab_y_0, r_ab_y_0), r_ab_x_0, r_ab_x_0);
float32x4_t r_ab_n2_1 = vfmaq_f32(vmulq_f32(r_ab_y_1, r_ab_y_1), r_ab_x_1, r_ab_x_1);
r_ab_n2_0 = vmaxq_f32(r_ab_n2_0, v_eps_sq);
r_ab_n2_1 = vmaxq_f32(r_ab_n2_1, v_eps_sq);
// # 8 ADD, 32 MULTS, 8 SQRT, 8 DIV
float32x4_t inv_r_ab_n_0 = _neon_rsqrt_ps(r_ab_n2_0);
float32x4_t inv_r_ab_n_1 = _neon_rsqrt_ps(r_ab_n2_1);
// # 8 MULTS
float32x4_t r_ab_n_0 = vmulq_f32(r_ab_n2_0, inv_r_ab_n_0);
float32x4_t r_ab_n_1 = vmulq_f32(r_ab_n2_1, inv_r_ab_n_1);
// # 16 ADDS
float32x4_t r_ab2_x_0 = vsubq_f32(r_ab_x_0, sbe_jx_0);
float32x4_t r_ab2_x_1 = vsubq_f32(r_ab_x_1, sbe_jx_1);
float32x4_t r_ab2_y_0 = vsubq_f32(r_ab_y_0, sbe_jy_0);
float32x4_t r_ab2_y_1 = vsubq_f32(r_ab_y_1, sbe_jy_1);
// # 8 ADDS, 16 MULTS
float32x4_t r_ab2_n2_0 = vfmaq_f32(vmulq_f32(r_ab2_y_0, r_ab2_y_0), r_ab2_x_0, r_ab2_x_0);
float32x4_t r_ab2_n2_1 = vfmaq_f32(vmulq_f32(r_ab2_y_1, r_ab2_y_1), r_ab2_x_1, r_ab2_x_1);
r_ab2_n2_0 = vmaxq_f32(r_ab2_n2_0, v_eps_sq);
r_ab2_n2_1 = vmaxq_f32(r_ab2_n2_1, v_eps_sq);
// # 8 ADD, 32 MULTS, 8 SQRT, 8 DIV
float32x4_t inv_r_ab2_n_0 = _neon_rsqrt_ps(r_ab2_n2_0);
float32x4_t inv_r_ab2_n_1 = _neon_rsqrt_ps(r_ab2_n2_1);
// # 8 MULTS
float32x4_t r_ab2_n_0 = vmulq_f32(r_ab2_n2_0, inv_r_ab2_n_0);
float32x4_t r_ab2_n_1 = vmulq_f32(r_ab2_n2_1, inv_r_ab2_n_1);
// # 8 ADDS
float32x4_t r_sum_0 = vaddq_f32(r_ab_n_0, r_ab2_n_0);
float32x4_t r_sum_1 = vaddq_f32(r_ab_n_1, r_ab2_n_1);
// # 8 ADDS, 8 MULTS
float32x4_t two_b_sq_0 = vsubq_f32(vmulq_f32(r_sum_0, r_sum_0), sb_jsq_0);
float32x4_t two_b_sq_1 = vsubq_f32(vmulq_f32(r_sum_1, r_sum_1), sb_jsq_1);
two_b_sq_0 = vmaxq_f32(two_b_sq_0, v_eps_sq);
two_b_sq_1 = vmaxq_f32(two_b_sq_1, v_eps_sq);
// # 8 ADD, 32 MULTS, 8 SQRT, 8 DIV
float32x4_t inv_two_b_0 = _neon_rsqrt_ps(two_b_sq_0);
float32x4_t inv_two_b_1 = _neon_rsqrt_ps(two_b_sq_1);
// # 8 MULTS
float32x4_t two_b_0 = vmulq_f32(two_b_sq_0, inv_two_b_0);
float32x4_t two_b_1 = vmulq_f32(two_b_sq_1, inv_two_b_1);
// # 8 MULTS
float32x4_t e_arg_0 = vmulq_f32(two_b_0, v_neg_2s_inv);
float32x4_t e_arg_1 = vmulq_f32(two_b_1, v_neg_2s_inv);
e_arg_0 = vmaxq_f32(e_arg_0, v_exp_min);
e_arg_1 = vmaxq_f32(e_arg_1, v_exp_min);
// # 128 MULTs, 112 ADDs
float32x4_t e_val_0 = _neon_exp_ps(e_arg_0);
float32x4_t e_val_1 = _neon_exp_ps(e_arg_1);
// # 24 MULTS
float32x4_t numer_inv_two_b_0 = vmulq_f32(vmulq_f32(r_sum_0, v_neg_v0_div_2s), vmulq_f32(e_val_0, inv_two_b_0));
float32x4_t numer_inv_two_b_1 = vmulq_f32(vmulq_f32(r_sum_1, v_neg_v0_div_2s), vmulq_f32(e_val_1, inv_two_b_1));
// # 16 MULTS
float32x4_t sm_r_ab_0 = vmulq_f32(numer_inv_two_b_0, inv_r_ab_n_0);
float32x4_t sm_r_ab_1 = vmulq_f32(numer_inv_two_b_1, inv_r_ab_n_1);
float32x4_t sm_r_ab2_0 = vmulq_f32(numer_inv_two_b_0, inv_r_ab2_n_0);
float32x4_t sm_r_ab2_1 = vmulq_f32(numer_inv_two_b_1, inv_r_ab2_n_1);
// # 16 ADDS, 32 MULTS
float32x4_t f_x_0 = vfmaq_f32(vmulq_f32(r_ab_x_0, sm_r_ab_0), r_ab2_x_0, sm_r_ab2_0);
float32x4_t f_x_1 = vfmaq_f32(vmulq_f32(r_ab_x_1, sm_r_ab_1), r_ab2_x_1, sm_r_ab2_1);
float32x4_t f_y_0 = vfmaq_f32(vmulq_f32(r_ab_y_0, sm_r_ab_0), r_ab2_y_0, sm_r_ab2_0);
float32x4_t f_y_1 = vfmaq_f32(vmulq_f32(r_ab_y_1, sm_r_ab_1), r_ab2_y_1, sm_r_ab2_1);
// # 8 ADDS, 16 MULTS
float32x4_t f_norm_sq_0 = vfmaq_f32(vmulq_f32(f_y_0, f_y_0), f_x_0, f_x_0);
float32x4_t f_norm_sq_1 = vfmaq_f32(vmulq_f32(f_y_1, f_y_1), f_x_1, f_x_1);
// # 8 MULTS
float32x4_t rhs_0 = vmulq_f32(f_norm_sq_0, v_cos_phi_sq);
float32x4_t rhs_1 = vmulq_f32(f_norm_sq_1, v_cos_phi_sq);
// # 8 ADDS, 16 MULTS
float32x4_t e_dot_f_0 = vfmaq_f32(vmulq_f32(eiy, f_y_0), eix, f_x_0);
float32x4_t e_dot_f_1 = vfmaq_f32(vmulq_f32(eiy, f_y_1), eix, f_x_1);
// # 8 MULTS
float32x4_t e_dot_f_sq_0 = vmulq_f32(e_dot_f_0, e_dot_f_0);
float32x4_t e_dot_f_sq_1 = vmulq_f32(e_dot_f_1, e_dot_f_1);
@@ -386,21 +466,26 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c
float32x4_t f_y_safe_0 = vbslq_f32(active_0, f_y_0, v_zero);
float32x4_t f_y_safe_1 = vbslq_f32(active_1, f_y_1, v_zero);
// # 16 ADDS, 16 MULTS
acc_x_0 = vfmaq_f32(acc_x_0, f_x_safe_0, w_val_0);
acc_x_1 = vfmaq_f32(acc_x_1, f_x_safe_1, w_val_1);
acc_y_0 = vfmaq_f32(acc_y_0, f_y_safe_0, w_val_0);
acc_y_1 = vfmaq_f32(acc_y_1, f_y_safe_1, w_val_1);
}
// # 16 ADDS
f_alpha_dt_x += vaddvq_f32(vaddq_f32(acc_x_0, acc_x_1));
f_alpha_dt_y += vaddvq_f32(vaddq_f32(acc_y_0, acc_y_1));
for (int k = 0; k < board.n_obstacles; k++) {
// # 2 ADDs
float v1_x = pos_x[i] - board.obstacles[k].start_x;
float v1_y = pos_y[i] - board.obstacles[k].start_y;
float v2_x = board.obstacles[k].obstacle_v_x;
float v2_y = board.obstacles[k].obstacle_v_y;
// # 3 MULTs, 1 ADD
float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv;
if (projection < 0.0f)
@@ -408,12 +493,15 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c
else if (projection > 1.0f)
projection = 1.0f;
// # 4 ADDs, 2 MULTs
float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection);
float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection);
// # 1 SQRT, 2 MULTs, 1 ADD
float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y);
r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS;
// # 4 MULTs, 1 EXP, 1 DIV
float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm;
float f_alpha_B_neg_x = r_aB_x * scalar_mult;
float f_alpha_B_neg_y = r_aB_y * scalar_mult;
@@ -424,13 +512,16 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c
if (e_dot_f < cos_phi)
w_val = c_neg_times_dt;
// # 2 MULTS
float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val;
float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val;
// # 2 ADDs
f_alpha_dt_x += f_alpha_B_dt_x;
f_alpha_dt_y += f_alpha_B_dt_y;
}
// # 2 ADDs
w_x[i] += f_alpha_dt_x;
w_y[i] += f_alpha_dt_y;
}
@@ -447,14 +538,22 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c
float32x4_t desired_v0_i_vec = vld1q_f32(&desired_v0[i]);
int32x4_t color_i_vec = vld1q_s32(&color[i]);
// # 4 ADDS, 8 MULTS
float32x4_t w_norm_sq = vfmaq_f32(vmulq_f32(w_y_i_vec, w_y_i_vec), w_x_i_vec, w_x_i_vec);
// # 4 ADD, 16 MULTS, 4 SQRT, 4 DIV
float32x4_t w_norm_inv = _neon_rsqrt_ps(w_norm_sq);
// # 4 MULTS
float32x4_t correction_factor = vminq_f32(v_one, vmulq_f32(v_max_i_vec, w_norm_inv));
// # 8 MULTS
float32x4_t curr_vel_x_i_vec = vmulq_f32(w_x_i_vec, correction_factor);
float32x4_t curr_vel_y_i_vec = vmulq_f32(w_y_i_vec, correction_factor);
const float32x4_t dt_vec = vdupq_n_f32(dt);
// # 8 ADDS, 8 MULTS
pos_x_i_vec = vfmaq_f32(pos_x_i_vec, curr_vel_x_i_vec, dt_vec);
pos_y_i_vec = vfmaq_f32(pos_y_i_vec, curr_vel_y_i_vec, dt_vec);
@@ -485,15 +584,27 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c
pos_y_i_vec = vmaxq_f32(pos_y_i_vec, vdupq_n_f32(WALL_EPS));
pos_y_i_vec = vminq_f32(pos_y_i_vec, vdupq_n_f32(BOARD_WIDTH_MINUS_WALL_EPS));
// # 8 ADDS
float32x4_t ex_vec = vsubq_f32(destination_x_i_vec, pos_x_i_vec);
float32x4_t ey_vec = vsubq_f32(destination_y_i_vec, pos_y_i_vec);
// # 4 ADDS, 8 MULTS
float32x4_t e_norm_sq = vfmaq_f32(vmulq_f32(ey_vec, ey_vec), ex_vec, ex_vec);
// # 4 ADD, 16 MULTS, 4 SQRT, 4 DIV
float32x4_t e_norm_inv = _neon_rsqrt_ps(e_norm_sq);
// # 8 MULTS
float32x4_t e_x_i_vec = vmulq_f32(ex_vec, e_norm_inv);
float32x4_t e_y_i_vec = vmulq_f32(ey_vec, e_norm_inv);
// # 4 ADDS, 8 MULTS
float32x4_t vel_norm_sq = vfmaq_f32(vmulq_f32(curr_vel_y_i_vec, curr_vel_y_i_vec), curr_vel_x_i_vec, curr_vel_x_i_vec);
// # 4 MULTS
float32x4_t sb_sq_i_vec = vmulq_f32(vel_norm_sq, vdupq_n_f32(delta_t_sq));
// # 4 SQRT
float32x4_t vel_norm_dt = vsqrtq_f32(sb_sq_i_vec); // full-precision sqrt, matches AVX-512
vst1q_f32(&curr_vel_x[i], curr_vel_x_i_vec);
@@ -506,6 +617,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c
vst1q_f32(&e_y[i], e_y_i_vec);
vst1q_f32(&destination_y[i], destination_y_i_vec);
vst1q_f32(&sb_sq[i], sb_sq_i_vec);
// # 8 MULTS
vst1q_f32(&sb_e_x[i], vmulq_f32(e_x_i_vec, vel_norm_dt));
vst1q_f32(&sb_e_y[i], vmulq_f32(e_y_i_vec, vel_norm_dt));
}