From 7203701ec428d10ed5a14f77f3920ff50653e43c Mon Sep 17 00:00:00 2001 From: EbbDrop Date: Sun, 8 Dec 2024 17:28:09 +0100 Subject: [PATCH 1/6] Switch to nightly --- rust-toolchain.toml | 2 ++ src/lib.rs | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 rust-toolchain.toml diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..3462712 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2024-12-04" diff --git a/src/lib.rs b/src/lib.rs index b7cfdd1..abfbb32 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(portable_simd)] + use aoc_runner_derive::aoc_lib; pub mod day1; From b22baf752d2c24f2296d145bbecbe6524e7f996a Mon Sep 17 00:00:00 2001 From: EbbDrop Date: Sun, 8 Dec 2024 17:53:04 +0100 Subject: [PATCH 2/6] Make simd version for part 1 --- src/day8.rs | 64 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/src/day8.rs b/src/day8.rs index 3b9ec96..0f42e2f 100644 --- a/src/day8.rs +++ b/src/day8.rs @@ -3,6 +3,8 @@ use tinyvec::ArrayVec; use crate::memchr_inv::OneInv; +use std::simd::prelude::*; + #[cfg(not(test))] const SIZE: i32 = 50; #[cfg(test)] @@ -46,31 +48,57 @@ fn part1_inner(s: &str) -> u64 { let new_x = i % SIZE1; let new_y = i / SIZE1; - // numbers[masts[f as usize].len()] += 1; + let masts = &mut masts[f as usize]; - for mast_i in &masts[f as usize] { - let mast_x = mast_i % SIZE1; - let mast_y = mast_i / SIZE1; + match masts.as_slice() { + [] => {} + [mast_i] => { + let mast_x = mast_i % SIZE1; + let mast_y = mast_i / SIZE1; - let diff_x = mast_x - new_x; - let diff_y = (new_y - mast_y).abs() as i32; - - let node_x = mast_x + diff_x; - if node_x >= 0 && node_x < SIZE && mast_y >= diff_y { - let node_y = mast_y - diff_y; + let node_x = mast_x + mast_x - new_x; + let node_y = mast_y - new_y + mast_y; + if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { + set_node(node_x, node_y); + } - set_node(node_x, node_y); + let node_x = new_x - mast_x + new_x; + let node_y = new_y + new_y - mast_y; + if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { + set_node(node_x, node_y); + } } - - let node_x = new_x - diff_x; - if node_x >= 0 && node_x < SIZE && new_y + diff_y < SIZE { - let node_y = new_y + diff_y; - - set_node(node_x, node_y); + masts => { + let mast_is = i32x4::load_or_default(masts); + let mast_xs = mast_is % i32x4::splat(SIZE1); + let mast_ys = mast_is / i32x4::splat(SIZE1); + + let new_xs = i32x4::splat(new_x); + let new_ys = i32x4::splat(new_y); + + let node1_xs = mast_xs + mast_xs - new_xs; + let node1_ys = mast_ys + mast_ys - new_ys; + + let node2_xs = new_xs + new_xs - mast_xs; + let node2_ys = new_ys + new_ys - mast_ys; + + for i in 0..masts.len() { + let node_x = node1_xs.as_array()[i]; + let node_y = node1_ys.as_array()[i]; + if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { + set_node(node_x, node_y); + } + + let node_x = node2_xs.as_array()[i]; + let node_y = node2_ys.as_array()[i]; + if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { + set_node(node_x, node_y); + } + } } } - masts[f as usize].push(i); + masts.push(i); } // for i in 0..5 { From 42674796390a746e0994c797c45bfb0e31f62252 Mon Sep 17 00:00:00 2001 From: EbbDrop Date: Sun, 8 Dec 2024 17:58:08 +0100 Subject: [PATCH 3/6] Dont special case size 1 --- src/day8.rs | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/day8.rs b/src/day8.rs index 0f42e2f..af146bb 100644 --- a/src/day8.rs +++ b/src/day8.rs @@ -22,7 +22,8 @@ pub fn part1(s: &str) -> u64 { } } -fn part1_inner(s: &str) -> u64 { +#[target_feature(enable = "avx2,bmi1,bmi2,cmpxchg16b,lzcnt,movbe,popcnt")] +unsafe fn part1_inner(s: &str) -> u64 { let s = s.as_bytes(); let mut masts: [ArrayVec<[i32; 4]>; FREQ_RANGE] = @@ -52,22 +53,22 @@ fn part1_inner(s: &str) -> u64 { match masts.as_slice() { [] => {} - [mast_i] => { - let mast_x = mast_i % SIZE1; - let mast_y = mast_i / SIZE1; - - let node_x = mast_x + mast_x - new_x; - let node_y = mast_y - new_y + mast_y; - if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { - set_node(node_x, node_y); - } - - let node_x = new_x - mast_x + new_x; - let node_y = new_y + new_y - mast_y; - if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { - set_node(node_x, node_y); - } - } + // [mast_i] => { + // let mast_x = mast_i % SIZE1; + // let mast_y = mast_i / SIZE1; + + // let node_x = mast_x + mast_x - new_x; + // let node_y = mast_y - new_y + mast_y; + // if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { + // set_node(node_x, node_y); + // } + + // let node_x = new_x - mast_x + new_x; + // let node_y = new_y + new_y - mast_y; + // if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { + // set_node(node_x, node_y); + // } + // } masts => { let mast_is = i32x4::load_or_default(masts); let mast_xs = mast_is % i32x4::splat(SIZE1); From fa34ecd9eb0dd75e38801070c6e14bf9d9107538 Mon Sep 17 00:00:00 2001 From: EbbDrop Date: Sun, 8 Dec 2024 18:25:45 +0100 Subject: [PATCH 4/6] Special case it again --- src/day8.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/day8.rs b/src/day8.rs index af146bb..feab466 100644 --- a/src/day8.rs +++ b/src/day8.rs @@ -53,22 +53,22 @@ unsafe fn part1_inner(s: &str) -> u64 { match masts.as_slice() { [] => {} - // [mast_i] => { - // let mast_x = mast_i % SIZE1; - // let mast_y = mast_i / SIZE1; - - // let node_x = mast_x + mast_x - new_x; - // let node_y = mast_y - new_y + mast_y; - // if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { - // set_node(node_x, node_y); - // } - - // let node_x = new_x - mast_x + new_x; - // let node_y = new_y + new_y - mast_y; - // if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { - // set_node(node_x, node_y); - // } - // } + [mast_i] => { + let mast_x = mast_i % SIZE1; + let mast_y = mast_i / SIZE1; + + let node_x = mast_x + mast_x - new_x; + let node_y = mast_y - new_y + mast_y; + if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { + set_node(node_x, node_y); + } + + let node_x = new_x - mast_x + new_x; + let node_y = new_y + new_y - mast_y; + if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { + set_node(node_x, node_y); + } + } masts => { let mast_is = i32x4::load_or_default(masts); let mast_xs = mast_is % i32x4::splat(SIZE1); From c7a82f5e8cdcf447f3baaf59e8d042b1111663bb Mon Sep 17 00:00:00 2001 From: EbbDrop Date: Sun, 8 Dec 2024 18:38:41 +0100 Subject: [PATCH 5/6] WIP Serperate parsing --- src/day8.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/day8.rs b/src/day8.rs index feab466..837149b 100644 --- a/src/day8.rs +++ b/src/day8.rs @@ -29,14 +29,6 @@ unsafe fn part1_inner(s: &str) -> u64 { let mut masts: [ArrayVec<[i32; 4]>; FREQ_RANGE] = [ArrayVec::from_array_empty([0; 4]); FREQ_RANGE]; - let mut antinodes = [false; (SIZE * SIZE) as usize]; - let mut total_antinotedes = 0; - - let mut set_node = |x, y| { - total_antinotedes += !antinodes[(y * SIZE + x) as usize] as u64; - antinodes[(y * SIZE + x) as usize] = true; - }; - // let mut numbers = [0; 5]; for i in unsafe { OneInv::new_unchecked(b'.').iter(s) } { @@ -46,16 +38,25 @@ unsafe fn part1_inner(s: &str) -> u64 { let f = s[i] - b'0'; let i = i as i32; - let new_x = i % SIZE1; - let new_y = i / SIZE1; + masts[f as usize].push(i); + } + + let mut antinodes = [false; (SIZE * SIZE) as usize]; + let mut total_antinotedes = 0; - let masts = &mut masts[f as usize]; + let mut set_node = |x, y| { + total_antinotedes += !antinodes[(y * SIZE + x) as usize] as u64; + antinodes[(y * SIZE + x) as usize] = true; + }; + for mast in masts { match masts.as_slice() { [] => {} - [mast_i] => { + [mast_i, new_i] => { let mast_x = mast_i % SIZE1; let mast_y = mast_i / SIZE1; + let new_x = new_i % SIZE1; + let new_y = new_i / SIZE1; let node_x = mast_x + mast_x - new_x; let node_y = mast_y - new_y + mast_y; @@ -98,8 +99,6 @@ unsafe fn part1_inner(s: &str) -> u64 { } } } - - masts.push(i); } // for i in 0..5 { From 9ba27820744db4a37625ae0da7b14b6c1d3a32d0 Mon Sep 17 00:00:00 2001 From: EbbDrop Date: Sun, 8 Dec 2024 18:59:58 +0100 Subject: [PATCH 6/6] Try simd after parsing --- src/day8.rs | 142 ++++++++++++++++++++++------------------------------ 1 file changed, 61 insertions(+), 81 deletions(-) diff --git a/src/day8.rs b/src/day8.rs index 837149b..873fcb1 100644 --- a/src/day8.rs +++ b/src/day8.rs @@ -16,10 +16,7 @@ const FREQ_RANGE: usize = (b'z' - b'0' + 1) as usize; #[aoc(day8, part1)] pub fn part1(s: &str) -> u64 { - #[expect(unused_unsafe)] - unsafe { - part1_inner(s) - } + unsafe { part1_inner(s) } } #[target_feature(enable = "avx2,bmi1,bmi2,cmpxchg16b,lzcnt,movbe,popcnt")] @@ -49,60 +46,51 @@ unsafe fn part1_inner(s: &str) -> u64 { antinodes[(y * SIZE + x) as usize] = true; }; - for mast in masts { - match masts.as_slice() { - [] => {} - [mast_i, new_i] => { - let mast_x = mast_i % SIZE1; - let mast_y = mast_i / SIZE1; - let new_x = new_i % SIZE1; - let new_y = new_i / SIZE1; - - let node_x = mast_x + mast_x - new_x; - let node_y = mast_y - new_y + mast_y; - if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { - set_node(node_x, node_y); - } + for masts in masts { + for i in 0..masts.len() { + let new_x = masts[i] % SIZE1; + let new_y = masts[i] / SIZE1; - let node_x = new_x - mast_x + new_x; - let node_y = new_y + new_y - mast_y; - if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { - set_node(node_x, node_y); - } - } - masts => { - let mast_is = i32x4::load_or_default(masts); - let mast_xs = mast_is % i32x4::splat(SIZE1); - let mast_ys = mast_is / i32x4::splat(SIZE1); + let mast_is = i32x4::load_or_default(&masts); + let mast_xs = mast_is % i32x4::splat(SIZE1); + let mast_ys = mast_is / i32x4::splat(SIZE1); - let new_xs = i32x4::splat(new_x); - let new_ys = i32x4::splat(new_y); + let new_xs = i32x4::splat(new_x); + let new_ys = i32x4::splat(new_y); - let node1_xs = mast_xs + mast_xs - new_xs; - let node1_ys = mast_ys + mast_ys - new_ys; + let node_xs = mast_xs + mast_xs - new_xs; + let node_ys = mast_ys + mast_ys - new_ys; - let node2_xs = new_xs + new_xs - mast_xs; - let node2_ys = new_ys + new_ys - mast_ys; + let node_xs = node_xs.as_array(); + let node_ys = node_ys.as_array(); - for i in 0..masts.len() { - let node_x = node1_xs.as_array()[i]; - let node_y = node1_ys.as_array()[i]; - if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { - set_node(node_x, node_y); - } + for other_i in 0..masts.len() { + if other_i == i { + continue; + } - let node_x = node2_xs.as_array()[i]; - let node_y = node2_ys.as_array()[i]; - if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { - set_node(node_x, node_y); - } + let node_x = node_xs[other_i]; + let node_y = node_ys[other_i]; + + if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { + set_node(node_x, node_y); } } } } - // for i in 0..5 { - // println!("{i}: {}", numbers[i]); + // for y in 0..SIZE { + // for x in 0..SIZE { + // print!( + // "{}", + // if antinodes[(y * SIZE + x) as usize] { + // '#' + // } else { + // s[(y * SIZE1 + x) as usize] as char + // } + // ) + // } + // println!(""); // } total_antinotedes @@ -122,12 +110,7 @@ fn part2_inner(s: &str) -> u64 { let mut masts: [ArrayVec<[i32; 4]>; FREQ_RANGE] = [ArrayVec::from_array_empty([0; 4]); FREQ_RANGE]; - let mut antinodes = [false; (SIZE * SIZE) as usize]; - let mut total_antinotedes = 0; - let mut set_node = |x, y| { - total_antinotedes += !antinodes[(y * SIZE + x) as usize] as u64; - antinodes[(y * SIZE + x) as usize] = true; - }; + // let mut numbers = [0; 5]; for i in unsafe { OneInv::new_unchecked(b'.').iter(s) } { if s[i] == b'\n' { @@ -136,44 +119,41 @@ fn part2_inner(s: &str) -> u64 { let f = s[i] - b'0'; let i = i as i32; - let new_x = i % SIZE1; - let new_y = i / SIZE1; - for mast_i in &masts[f as usize] { - let mast_x = mast_i % SIZE1; - let mast_y = mast_i / SIZE1; - - let o_diff_x = mast_x - new_x; - let o_diff_y = (new_y - mast_y).abs() as i32; + masts[f as usize].push(i); + } - for k in 0.. { - let diff_x = o_diff_x * k; - let diff_y = o_diff_y * k; + let mut antinodes = [false; (SIZE * SIZE) as usize]; + let mut total_antinotedes = 0; - let mut new_node = false; + let mut set_node = |x, y| { + total_antinotedes += !antinodes[(y * SIZE + x) as usize] as u64; + antinodes[(y * SIZE + x) as usize] = true; + }; - let node_x = mast_x + diff_x; - if node_x >= 0 && node_x < SIZE && mast_y >= diff_y { - let node_y = mast_y - diff_y; + for masts in masts { + for i in 0..masts.len() { + let new_x = masts[i] % SIZE1; + let new_y = masts[i] / SIZE1; - new_node = true; - set_node(node_x, node_y); + for other_i in 0..masts.len() { + if other_i == i { + continue; } + let mast_x = masts[other_i] % SIZE1; + let mast_y = masts[other_i] / SIZE1; - let node_x = new_x - diff_x; - if node_x >= 0 && node_x < SIZE && new_y + diff_y < SIZE { - let node_y = new_y + diff_y; - - new_node = true; - set_node(node_x, node_y); - } + for k in 0.. { + let node_x = mast_x + (mast_x - new_x) * k; + let node_y = mast_y + (mast_y - new_y) * k; - if !new_node { - break; + if node_x >= 0 && node_x < SIZE && node_y >= 0 && node_y < SIZE { + set_node(node_x, node_y); + } else { + break; + } } } } - - masts[f as usize].push(i); } total_antinotedes