[rs] Parallelize 2022_16 part 2

This commit is contained in:
Joscha 2022-12-16 14:39:13 +01:00
parent 4f9de30212
commit efaaef4e6a
3 changed files with 193 additions and 53 deletions

120
rs/Cargo.lock generated
View file

@ -7,8 +7,15 @@ name = "aoc-rs"
version = "0.0.0"
dependencies = [
"clap",
"rayon",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -21,6 +28,12 @@ version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.0.29"
@ -58,6 +71,55 @@ dependencies = [
"os_str_bytes",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
]
[[package]]
name = "either"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "errno"
version = "0.2.8"
@ -85,6 +147,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
@ -110,7 +181,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330"
dependencies = [
"hermit-abi",
"hermit-abi 0.2.6",
"io-lifetimes",
"rustix",
"windows-sys",
@ -128,6 +199,25 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
[[package]]
name = "memoffset"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
dependencies = [
"hermit-abi 0.1.19",
"libc",
]
[[package]]
name = "once_cell"
version = "1.16.0"
@ -182,6 +272,28 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
name = "rustix"
version = "0.36.4"
@ -196,6 +308,12 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "strsim"
version = "0.10.0"

View file

@ -5,3 +5,4 @@ edition = "2021"
[dependencies]
clap = { version = "4.0.29", features = ["derive", "deprecated"] }
rayon = "1.6.1"

View file

@ -1,6 +1,10 @@
use std::collections::HashMap;
use std::mem;
use rayon::prelude::{
IndexedParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator,
};
fn parse_valve(line: &str) -> (&str, u32, Vec<&str>) {
let (name, rest) = line
.strip_prefix("Valve ")
@ -168,47 +172,23 @@ impl Dp2 {
let id = self.powers * (self.valves * own_id + el_id) + open.0 as usize;
self.elems[id]
}
fn set(&mut self, own_id: usize, el_id: usize, open: OpenSet, score: u32) {
let id = self.powers * (self.valves * own_id + el_id) + open.0 as usize;
self.elems[id] = score;
}
fn clear(&mut self) {
self.elems.fill(0);
}
}
fn solve_part_2(names: &HashMap<&str, usize>, valves: &[Valve], powerset: &[OpenSet]) -> u32 {
// DP state consists of:
// - The own valve
// - The elephant valve
// - The set of open/closed valves
let mut prev = Dp2::new(valves, powerset);
let mut curr = Dp2::new(valves, powerset);
// Given valve v in minute t with set s, you can either...
// - I move, elephant moves
// - I move, elephant opens valve
// - I open valve, elephant moves
// - I open valve, elephant opens valve (if not in same room)
for minute in 1..=26 {
eprintln!("Minute {minute}");
mem::swap(&mut curr, &mut prev);
curr.clear();
for (own_id, own_valve) in valves.iter().enumerate() {
for (el_id, el_valve) in valves.iter().enumerate() {
for open in powerset {
fn part_2_score(
minute: u32,
prev: &Dp2,
own_id: usize,
own_valve: &Valve,
el_id: usize,
el_valve: &Valve,
open: OpenSet,
) -> u32 {
let mut score = 0;
// Both move
for own_next in &own_valve.next {
for el_next in &el_valve.next {
score = score.max(prev.get(*own_next, *el_next, *open));
score = score.max(prev.get(*own_next, *el_next, open));
}
}
@ -242,10 +222,51 @@ fn solve_part_2(names: &HashMap<&str, usize>, valves: &[Valve], powerset: &[Open
score = score.max(room_but_valves_open + pressure_until_end);
}
curr.set(own_id, el_id, *open, score);
score
}
fn solve_part_2(names: &HashMap<&str, usize>, valves: &[Valve], powerset: &[OpenSet]) -> u32 {
// DP state consists of:
// - The own valve
// - The elephant valve
// - The set of open/closed valves
let mut prev = Dp2::new(valves, powerset);
let mut curr = Dp2::new(valves, powerset);
// Given valve v in minute t with set s, you can either...
// - I move, elephant moves
// - I move, elephant opens valve
// - I open valve, elephant moves
// - I open valve, elephant opens valve (if not in same room)
let mut variations = vec![];
for (own_id, own_valve) in valves.iter().enumerate() {
for (el_id, el_valve) in valves.iter().enumerate() {
for open in powerset {
variations.push((own_id, own_valve, el_id, el_valve, open));
}
}
}
// Just to check whether the variations are in the correct order because I'm
// zipping them to curr.elems later.
for (i, (own_id, _, el_id, _, open)) in variations.iter().enumerate() {
let id = curr.powers * (curr.valves * own_id + el_id) + open.0 as usize;
assert_eq!(i, id);
}
for minute in 1..=26 {
eprintln!("Minute {minute}");
mem::swap(&mut curr, &mut prev);
curr.elems
.par_iter_mut()
.zip(variations.par_iter())
.for_each(|(score, (own_id, own_valve, el_id, el_valve, open))| {
*score = part_2_score(minute, &prev, *own_id, own_valve, *el_id, el_valve, **open);
});
}
curr.get(names["AA"], names["AA"], OpenSet::ALL_CLOSED)