simd opti

This commit is contained in:
2026-05-11 12:08:06 +02:00
parent 98a3422fc3
commit 9c3fb79c00
23 changed files with 1102 additions and 179 deletions

View File

@ -3,7 +3,8 @@ use crate::code::{CodeTopology, GenerationMethod, LdpcCode, LdpcParams};
use crate::decoder::{build_decoder, DecoderConfig, DecoderMethod};
use crate::encoder::{build_encoder, EncodingMethod};
use crate::Result as LdpcResult;
use rand::{Rng, SeedableRng};
use rand::Rng;
use rayon::prelude::*;
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
@ -37,13 +38,10 @@ pub fn run_simulation(mut code: LdpcCode) -> LdpcResult<()> {
}
);
println!("\n[*] Étape 2 : Extraction de G^T et Instanciation de l'Encodeur");
println!("\n[*] Étape 2 : Instanciation de l'Encodeur (SIMD Bit-Packing)");
let start_enc = Instant::now();
let encoder = build_encoder(&mut code, EncodingMethod::Systematic)?;
println!(
" - Forme systématique calculée en {:.2?}",
start_enc.elapsed()
);
println!(" - Encodeur prêt en {:.2?}", start_enc.elapsed());
println!("\n[*] Étape 3 : Instanciation des Décodeurs sur Graphe");
let config = DecoderConfig {
@ -62,12 +60,11 @@ pub fn run_simulation(mut code: LdpcCode) -> LdpcResult<()> {
let dec_bf = build_decoder(&code, DecoderMethod::BitFlipping, config.clone());
println!(" - Moteurs prêts : Sum-Product, Min-Sum (α=0.8), Bit-Flipping");
let snr_range = [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0];
let n_trials = 100;
let mut rng = rand::rngs::StdRng::seed_from_u64(42);
let snr_range = [1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 3.0, 3.5, 4.0];
let n_trials = 1000;
println!(
"\n[*] Étape 4 : Simulation sur Canal AWGN ({} trames par SNR)",
"\n[*] Étape 4 : Simulation sur Canal AWGN ({} trames par SNR, Multi-threadé)",
n_trials
);
println!("{:-<115}", "");
@ -86,6 +83,67 @@ pub fn run_simulation(mut code: LdpcCode) -> LdpcResult<()> {
for &snr in &snr_range {
let channel = AwgnChannel::new(snr, code.rate())?;
let results: Vec<_> = (0..n_trials)
.into_par_iter()
.map(|_| {
let mut rng = rand::thread_rng();
let message: Vec<u8> = (0..code.k()).map(|_| rng.gen::<u8>() & 1).collect();
let codeword = encoder.encode(&message).unwrap();
let received_llr = channel.transmit(&codeword, &mut rng);
let mut t_sp_f = 0;
let mut t_sp_b = 0;
let mut t_ms_f = 0;
let mut t_ms_b = 0;
let mut t_bf_f = 0;
let mut t_bf_b = 0;
// SP
let res_sp = dec_sp.decode(&received_llr);
if let Some(decoded) = res_sp.codeword() {
let errs = count_bit_errors(&codeword, decoded);
if errs > 0 {
t_sp_f = 1;
t_sp_b = errs;
}
} else {
t_sp_f = 1;
t_sp_b = code.n();
}
// MS
let res_ms = dec_ms.decode(&received_llr);
if let Some(decoded) = res_ms.codeword() {
let errs = count_bit_errors(&codeword, decoded);
if errs > 0 {
t_ms_f = 1;
t_ms_b = errs;
}
} else {
t_ms_f = 1;
t_ms_b = code.n();
}
// BF
let res_bf = dec_bf.decode(&received_llr);
if let Some(decoded) = res_bf.codeword() {
let errs = count_bit_errors(&codeword, decoded);
if errs > 0 {
t_bf_f = 1;
t_bf_b = errs;
}
} else {
t_bf_f = 1;
t_bf_b = code.n();
}
(t_sp_f, t_sp_b, t_ms_f, t_ms_b, t_bf_f, t_bf_b)
})
.collect();
// Agrégation
let mut err_sp_frames = 0;
let mut err_sp_bits = 0;
let mut err_ms_frames = 0;
@ -93,49 +151,13 @@ pub fn run_simulation(mut code: LdpcCode) -> LdpcResult<()> {
let mut err_bf_frames = 0;
let mut err_bf_bits = 0;
for _ in 0..n_trials {
let message: Vec<u8> = (0..code.k()).map(|_| rng.gen::<u8>() & 1).collect();
let codeword = encoder.encode(&message)?;
let received_llr = channel.transmit(&codeword, &mut rng);
// SP
let res_sp = dec_sp.decode(&received_llr);
if let Some(decoded) = res_sp.codeword() {
let errs = count_bit_errors(&codeword, decoded);
if errs > 0 {
err_sp_frames += 1;
err_sp_bits += errs;
}
} else {
err_sp_frames += 1;
err_sp_bits += code.n();
}
// MS
let res_ms = dec_ms.decode(&received_llr);
if let Some(decoded) = res_ms.codeword() {
let errs = count_bit_errors(&codeword, decoded);
if errs > 0 {
err_ms_frames += 1;
err_ms_bits += errs;
}
} else {
err_ms_frames += 1;
err_ms_bits += code.n();
}
// BF
let res_bf = dec_bf.decode(&received_llr);
if let Some(decoded) = res_bf.codeword() {
let errs = count_bit_errors(&codeword, decoded);
if errs > 0 {
err_bf_frames += 1;
err_bf_bits += errs;
}
} else {
err_bf_frames += 1;
err_bf_bits += code.n();
}
for res in results {
err_sp_frames += res.0;
err_sp_bits += res.1;
err_ms_frames += res.2;
err_ms_bits += res.3;
err_bf_frames += res.4;
err_bf_bits += res.5;
}
let total_bits = (n_trials * code.n()) as f64;
@ -162,39 +184,39 @@ fn count_bit_errors(transmitted: &[u8], decoded: &[u8]) -> usize {
.count()
}
pub fn generate_valid_code(
n: usize,
k: usize,
wc: usize,
wr: usize,
generation_method: GenerationMethod,
) -> LdpcResult<LdpcCode> {
let mut attempt = 0;
let start_gen = Instant::now();
loop {
attempt += 1;
let params = LdpcParams {
n,
k,
topology: CodeTopology::Regular { wc, wr },
generation: generation_method.clone(),
seed: Some(rand::random()),
};
if let Ok(mut code) = LdpcCode::new(params) {
if code.compute_systematic_form().is_ok() {
if attempt > 1 {
println!(
" -> Matrice inversible obtenue après {} tentatives.",
attempt
);
}
println!(" - Génération : Terminée en {:.2?}", start_gen.elapsed());
return Ok(code);
}
}
}
}
// pub fn generate_valid_code(
// n: usize,
// k: usize,
// wc: usize,
// wr: usize,
// generation_method: GenerationMethod,
// ) -> LdpcResult<LdpcCode> {
// let mut attempt = 0;
// let start_gen = Instant::now();
// loop {
// attempt += 1;
// let params = LdpcParams {
// n,
// k,
// topology: CodeTopology::Regular { wc, wr },
// generation: generation_method.clone(),
// seed: Some(rand::random()),
// };
//
// if let Ok(mut code) = LdpcCode::new(params) {
// if code.compute_systematic_form().is_ok() {
// if attempt > 1 {
// println!(
// " -> Matrice inversible obtenue après {} tentatives.",
// attempt
// );
// }
// println!(" - Génération : Terminée en {:.2?}", start_gen.elapsed());
// return Ok(code);
// }
// }
// }
// }
pub fn get_or_generate_cached_code(
n: usize,