Implement a 'SerializerRenderer' output format

It's CBOR, which seems to pack not so efficiently (250*250*20 * 12
floats takes 400 MB per frame, whereas this many doubles could pack into
120 MB). serde_cbor also seems to be extremely slow: taking multiple
minutes per frame. This could be parallelized to be less problematic
though (it already is -- just bump the parallelism).

Might be worth testing other formats.
This commit is contained in:
Colin 2020-11-27 22:11:53 -08:00
parent 9d15e126a7
commit 2c042810d8
8 changed files with 48 additions and 11 deletions

View File

@ -17,9 +17,11 @@ image = "0.23"
imageproc = "0.21"
lazy_static = "1.4"
log = "0.4"
ndarray = { version = "0.13", features = ["rayon"] }
ndarray = { version = "0.13", features = ["rayon", "serde"] }
piecewise-linear = "0.1"
plotly = { version = "0.6", features = ["kaleido", "plotly_ndarray"], path = "../plotly/plotly" }
serde = "1.0"
serde_cbor = "0.11"
threadpool = "1.8"
y4m = "0.7"

View File

@ -38,7 +38,7 @@ fn main() {
//driver.set_steps_per_frame(120);
driver.set_steps_per_frame(160);
//driver.set_steps_per_frame(200);
let base = "toroid25d-7";
let base = "toroid25d-8";
let _ = std::fs::create_dir(base);
let prefix = format!("{}/{}-flt{}-{}-feat{}um-{}mA-{}ps--radii{}um-{}um-{}um-{}um",
base,
@ -54,8 +54,9 @@ fn main() {
m_to_um(ferro_depth),
);
let _ = std::fs::create_dir(&prefix);
driver.add_y4m_renderer(&*format!("{}.y4m", prefix));
driver.add_plotly_renderer(&*format!("{}/frame-", prefix));
//driver.add_y4m_renderer(&*format!("{}.y4m", prefix));
//driver.add_plotly_renderer(&*format!("{}/frame-", prefix));
driver.add_serializer_renderer(&*format!("{}/frame-", prefix));
let conductor_region = CylinderZ::new(
Vec2::new(half_width, half_width),
conductor_outer_rad);

View File

@ -83,6 +83,10 @@ impl Driver {
self.add_renderer(render::ColorTermRenderer, "terminal");
}
pub fn add_serializer_renderer(&mut self, out_base: &str) {
self.add_renderer(render::SerializerRenderer::new(out_base), out_base);
}
// pub fn add_boundary(&mut self, thickness: u32, base_conductivity: Flt) {
// for inset in 0..thickness {
// let depth = thickness - inset;

View File

@ -1,5 +1,7 @@
use crate::flt::{Flt, Real};
use super::Vec3u;
use serde::{Serialize, Deserialize};
use std::convert::From;
use std::iter::Sum;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub};
@ -8,7 +10,7 @@ fn round(f: Real) -> Real {
Real::from_inner(f.into_inner().round())
}
#[derive(Copy, Clone, Debug, Default)]
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct Vec2 {
pub x: Real,
pub y: Real,
@ -115,7 +117,7 @@ impl Vec2 {
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Vec3 {
pub(crate) x: Real,
pub(crate) y: Real,

View File

@ -1,7 +1,9 @@
use super::Vec3;
use serde::{Serialize, Deserialize};
use std::fmt::{self, Display};
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct Vec3u {
y: u32,
x: u32,

View File

@ -1,9 +1,11 @@
use crate::{CellState, consts};
use crate::flt::{Flt, Real};
use crate::geom::{Line2d, Vec2, Vec3, Polygon2d};
use lazy_static::lazy_static;
use log::{debug, trace};
use enum_dispatch::enum_dispatch;
use serde::{Serialize, Deserialize};
use std::cmp::Ordering;
#[enum_dispatch]
@ -27,7 +29,7 @@ pub trait Material {
}
}
#[derive(Clone, Default)]
#[derive(Clone, Default, Serialize, Deserialize)]
pub struct Static {
pub conductivity: Vec3,
pub m: Vec3,

View File

@ -462,3 +462,24 @@ impl Renderer for MultiRenderer {
}
}
}
pub struct SerializerRenderer {
out_base: String
}
impl SerializerRenderer {
pub fn new(out_base: &str) -> Self {
Self {
out_base: out_base.into(),
}
}
}
impl Renderer for SerializerRenderer {
fn render(&self, state: &dyn GenericSim, measurements: &[Box<dyn AbstractMeasurement>]) {
let snap = state.to_static();
let name = format!("{}{}.cbor", self.out_base, snap.step_no());
let out = File::create(name).unwrap();
serde_cbor::to_writer(out, &snap).unwrap();
}
}

View File

@ -6,6 +6,7 @@ use log::trace;
use ndarray::{Array3, Zip};
use ndarray::parallel::prelude::*;
use serde::{Serialize, Deserialize};
use std::convert::From;
use std::iter::Sum;
@ -34,6 +35,7 @@ pub trait GenericSim: Send + Sync + DynClone {
/// Take a "snapshot" of the simulation, dropping all material-specific information.
fn to_static(&self) -> SimState<mat::Static> {
let mut state = SimState::new(self.size(), self.feature_size());
state.step_no = self.step_no();
Zip::from(ndarray::indices_of(&state.cells)).par_apply_assign_into(
&mut state.cells,
|(z, y, x)| {
@ -96,9 +98,10 @@ impl<'a> dyn GenericSim + 'a {
}
}
#[derive(Default, Clone)]
#[derive(Default, Clone, Serialize, Deserialize)]
pub struct SimState<M=GenericMaterial> {
cells: Array3<Cell<M>>,
#[serde(skip)]
scratch: Array3<Cell<M>>,
feature_size: Real,
step_no: u64,
@ -277,7 +280,7 @@ impl<M> SimState<M> {
/// \| | |
/// +------------+------------+
///
#[derive(Clone, Default)]
#[derive(Clone, Default, Serialize, Deserialize)]
pub struct Cell<M = mat::Static> {
state: CellState,
mat: M,
@ -532,7 +535,7 @@ impl<M: Material> Cell<M> {
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct CellState {
e: Vec3,
h: Vec3,