-
Notifications
You must be signed in to change notification settings - Fork 353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve the record type performance #1151
Comments
It might be because of compression. There is an open bug the serialization does not finish if compression is enabled. We should check compressed and uncompressed. |
It is definitely related to the compression. I collected some reference numbers while I was working on my ResNet implementation (in release mode, because compression is even slower in debug mode).
The difference is quite substantial. Even if we switch from
The MessagePack format without compression is much faster, but does not provide checksum validation for corrupted files. Ideally we could provide a format that is faster than the current |
So I explored some alternatives to the gzip compression today, namely For Click for recorder implementationAdd the following to use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression};
/// File recorder using the [named msgpack](rmp_serde) format with zlib-ng.
#[derive(new, Debug, Default, Clone)]
pub struct NamedMpkZlibFileRecorder<S: PrecisionSettings> {
_settings: PhantomData<S>,
}
impl<S: PrecisionSettings> FileRecorder for NamedMpkZlibFileRecorder<S> {
fn file_extension() -> &'static str {
"zz"
}
}
impl<S: PrecisionSettings> Recorder for NamedMpkZlibFileRecorder<S> {
type Settings = S;
type RecordArgs = PathBuf;
type RecordOutput = ();
type LoadArgs = PathBuf;
fn save_item<I: Serialize>(
&self,
item: I,
mut file: Self::RecordArgs,
) -> Result<(), RecorderError> {
let writer = str2writer!(file)?;
let mut writer = ZlibEncoder::new(writer, Compression::default());
// let mut writer = ZlibEncoder::new(writer, Compression::fast());
rmp_serde::encode::write_named(&mut writer, &item)
.map_err(|err| RecorderError::Unknown(err.to_string()))?;
Ok(())
}
fn load_item<I: DeserializeOwned>(&self, mut file: Self::LoadArgs) -> Result<I, RecorderError> {
let reader = str2reader!(file)?;
let reader = ZlibDecoder::new(reader);
let state = rmp_serde::decode::from_read(reader)
.map_err(|err| RecorderError::Unknown(err.to_string()))?;
Ok(state)
}
} Note: requires
But when using the lowest compression level, it seems that
For Click for recorder implementationAdd the following to use lzzzz::lz4f::{ContentChecksum, PreferencesBuilder, ReadDecompressor, WriteCompressor};
/// File recorder using the [named msgpack](rmp_serde) format with lz4f compression.
#[derive(new, Debug, Default, Clone)]
pub struct NamedMpkLz4fFileRecorder<S: PrecisionSettings> {
_settings: PhantomData<S>,
}
impl<S: PrecisionSettings> FileRecorder for NamedMpkLz4fFileRecorder<S> {
fn file_extension() -> &'static str {
"lz4f"
}
}
impl<S: PrecisionSettings> Recorder for NamedMpkLz4fFileRecorder<S> {
type Settings = S;
type RecordArgs = PathBuf;
type RecordOutput = ();
type LoadArgs = PathBuf;
fn save_item<I: Serialize>(
&self,
item: I,
mut file: Self::RecordArgs,
) -> Result<(), RecorderError> {
let writer = str2writer!(file)?;
let pref = PreferencesBuilder::new()
.content_checksum(ContentChecksum::Enabled)
// .compression_level(6)
.build();
let mut writer = WriteCompressor::new(writer, pref)
.map_err(|err| RecorderError::Unknown(err.to_string()))?;
rmp_serde::encode::write_named(&mut writer, &item)
.map_err(|err| RecorderError::Unknown(err.to_string()))?;
Ok(())
}
fn load_item<I: DeserializeOwned>(&self, mut file: Self::LoadArgs) -> Result<I, RecorderError> {
let reader = str2reader!(file)?;
let reader =
ReadDecompressor::new(reader).map_err(|err| RecorderError::Unknown(err.to_string()))?;
let state = rmp_serde::decode::from_read(reader)
.map_err(|err| RecorderError::Unknown(err.to_string()))?;
Ok(state)
}
} Note: requires
When disabling the checksum we observe that the save and load times are slightly faster but there is still some overhead.
For usability, it still leaves much to be desired when loading simple models like a ResNet. TL;DR: as discussed offline with @nathanielsimard the current MessagePack serialization with /edit: This experiment was done for relatively small models.. I can't imagine how bad the user experience would be for even bigger models. See also: a note on checksum for loading/saving models |
Thanks for exploring alternatives. I agree we should make message pack default without compression. This is what I did for onnx default type when exporting. |
We also have https://github.com/memorysafety/zlib-rs as possible alternative, but it is still in an embronyal state. |
The current NamedMpkGz is too slow in term of serialization and deserialization, so we should investiguate alternatives or improve it.
The text was updated successfully, but these errors were encountered: