use crate::model::Layer;
pub fn layer_ic_parallelism(layer: &Layer, requested: u32) -> u32 {
let requested = requested.max(1);
if requested == 1 {
return 1;
}
match layer {
Layer::Conv2d {
c_in,
weight_bits,
w_zp,
..
} => {
if *weight_bits != 2 || *w_zp != 0 {
return 1;
}
if !(*c_in as u32).is_multiple_of(requested) {
return 1;
}
requested
}
_ => 1,
}
}
pub fn layer_parallelism(layer: &Layer, requested: u32) -> u32 {
let requested = requested.max(1);
if requested == 1 {
return 1;
}
match layer {
Layer::Conv2d { c_out, .. } if (*c_out as u32).is_multiple_of(requested) => requested,
Layer::Dense { .. } => 1,
_ => 1,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::model::tinyconv_mnist_from_cortexm;
#[test]
fn tinyconv_layer_eligibility_at_p4() {
let m = tinyconv_mnist_from_cortexm();
let p = m
.layers
.iter()
.map(|l| layer_parallelism(l, 4))
.collect::<Vec<_>>();
assert_eq!(p, vec![4, 1, 1, 4, 1, 1, 1, 1]);
}
#[test]
fn tinyconv_layer_eligibility_at_p8() {
let m = tinyconv_mnist_from_cortexm();
let p = m
.layers
.iter()
.map(|l| layer_parallelism(l, 8))
.collect::<Vec<_>>();
assert_eq!(p, vec![8, 1, 1, 8, 1, 1, 1, 1]);
}
#[test]
fn p_must_divide_c_out() {
let m = tinyconv_mnist_from_cortexm();
let conv1 = &m.layers[0];
assert_eq!(layer_parallelism(conv1, 3), 1);
}
#[test]
fn requested_one_is_passthrough() {
let m = tinyconv_mnist_from_cortexm();
for l in &m.layers {
assert_eq!(layer_parallelism(l, 1), 1);
}
}
}