Added generator of MD table with result of resizing speed comparison.

This commit is contained in:
Kirill Kuzminykh
2021-07-30 01:22:16 +03:00
parent d65f7c07ef
commit 69bef66fa1
11 changed files with 173 additions and 110 deletions
Generated
+33 -37
View File
@@ -22,15 +22,15 @@ checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
[[package]]
name = "anyhow"
version = "1.0.41"
version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
[[package]]
name = "argh"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91792f088f87cdc7a2cfb1d617fa5ea18d7f1dc22ef0e1b5f82f3157cdc522be"
checksum = "2e7317a549bc17c5278d9e72bb6e62c6aa801ac2567048e39ebc1c194249323e"
dependencies = [
"argh_derive",
"argh_shared",
@@ -38,9 +38,9 @@ dependencies = [
[[package]]
name = "argh_derive"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4eb0c0c120ad477412dc95a4ce31e38f2113e46bd13511253f79196ca68b067"
checksum = "60949c42375351e9442e354434b0cba2ac402c1237edf673cac3a4bf983b8d3c"
dependencies = [
"argh_shared",
"heck",
@@ -51,9 +51,9 @@ dependencies = [
[[package]]
name = "argh_shared"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "781f336cc9826dbaddb9754cb5db61e64cab4f69668bd19dcc4a0394a86f4cb1"
checksum = "8a61eb019cb8f415d162cb9f12130ee6bbe9168b7d953c17f4ad049e4051ca00"
[[package]]
name = "autocfg"
@@ -87,9 +87,9 @@ dependencies = [
[[package]]
name = "bytemuck"
version = "1.7.0"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9966d2ab714d0f785dbac0a0396251a35280aeb42413281617d0209ab4898435"
checksum = "72957246c41db82b8ef88a5486143830adeb8227ef9837740bdec67724cf2c5b"
[[package]]
name = "byteorder"
@@ -99,9 +99,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.68"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
dependencies = [
"jobserver",
]
@@ -491,9 +491,9 @@ dependencies = [
[[package]]
name = "instant"
version = "0.1.9"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d"
dependencies = [
"cfg-if",
]
@@ -530,9 +530,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.97"
version = "0.2.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
[[package]]
name = "libgit2-sys"
@@ -720,11 +720,11 @@ dependencies = [
[[package]]
name = "open"
version = "1.7.0"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1711eb4b31ce4ad35b0f316d8dfba4fe5c7ad601c448446d84aae7a896627b20"
checksum = "dcea7a30d6b81a2423cc59c43554880feff7b57d12916f231a79f8d6d9470201"
dependencies = [
"which",
"pathdiff",
"winapi",
]
@@ -753,6 +753,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "pathdiff"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877630b3de15c0b64cc52f659345724fbf6bdad9bd9566699fc53688f3c34a34"
[[package]]
name = "percent-encoding"
version = "2.1.0"
@@ -785,9 +791,9 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "proc-macro2"
version = "1.0.27"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
dependencies = [
"unicode-xid",
]
@@ -974,9 +980,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.64"
version = "1.0.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
checksum = "28c5e91e4240b46c4c19219d6cc84784444326131a4210f496f948d5cc827a29"
dependencies = [
"itoa",
"ryu",
@@ -1017,9 +1023,9 @@ checksum = "3bdb25a4593d6656239319426f4025f7a658157e25e89f0e0319d7516d46042d"
[[package]]
name = "syn"
version = "1.0.73"
version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
dependencies = [
"proc-macro2",
"quote",
@@ -1097,9 +1103,9 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "1.2.0"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342"
checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338"
dependencies = [
"tinyvec_macros",
]
@@ -1176,16 +1182,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e"
[[package]]
name = "which"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b55551e42cbdf2ce2bedd2203d0cc08dba002c27510f86dab6d0ce304cba3dfe"
dependencies = [
"either",
"libc",
]
[[package]]
name = "winapi"
version = "0.3.9"
+2 -2
View File
@@ -20,8 +20,8 @@ thiserror = "1.0.26"
[dev-dependencies]
glassbench = "0.3.0"
image = "0.23.14"
resize = "0.7.0"
rgb = "0.8.25"
resize = "0.7.2"
rgb = "0.8.27"
[[bench]]
+22 -21
View File
@@ -20,12 +20,13 @@ Environment:
- CPU: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz
- RAM: DDR4 3000 MHz
- Ubuntu 20.04 (linux 5.8)
- Rust 1.54
- fast_image_resize = "0.1"
- glassbench = "0.3.0"
Other Rust libraries used to compare of resizing speed:
- image = "0.23.14" (https://crates.io/crates/image)
- resize = "0.7.0" (https://crates.io/crates/resize)
- resize = "0.7.2" (https://crates.io/crates/resize)
Resize algorithms:
- Nearest
@@ -44,21 +45,21 @@ Pipeline:
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|------------|:-------:|:--------:|:----------:|:--------:|
| image | 106.841 | 205.303 | 302.171 | 400.717 |
| resize | 16.077 | 72.027 | 132.17 | 192.05 |
| fir rust | 0.477 | 57.038 | 87.254 | 120.589 |
| fir sse4.1 | - | 12.333 | 18.391 | 25.872 |
| fir avx2 | - | 9.369 | 13.371 | 19.002 |
| image | 105.194 | 198.359 | 289.810 | 381.861 |
| resize | 16.186 | 71.964 | 132.501 | 192.672 |
| fir rust | 0.476 | 55.284 | 84.732 | 117.519 |
| fir sse4.1 | - | 11.848 | 17.864 | 25.978 |
| fir avx2 | - | 8.753 | 12.569 | 18.112 |
Compiled with `rustflags = ["-C", "target-cpu=native"]`
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|------------|:-------:|:--------:|:----------:|:--------:|
| image | 91.607 | 184.2 | 280.471 | 382.259 |
| resize | 15.884 | 62.297 | 115.057 | 168.398 |
| fir rust | 0.473 | 56.827 | 62.832 | 84.949 |
| fir sse4.1 | - | 11.561 | 16.621 | 23.75 |
| fir avx2 | - | 8.747 | 11.873 | 17.31 |
| image | 91.138 | 182.251 | 279.838 | 380.956 |
| resize | 15.967 | 62.125 | 114.870 | 168.013 |
| fir rust | 0.467 | 56.376 | 61.565 | 85.433 |
| fir sse4.1 | - | 11.229 | 16.503 | 23.465 |
| fir avx2 | - | 8.464 | 11.602 | 17.076 |
### Resize RGBA image 4928x3279 => 852x567
@@ -71,21 +72,21 @@ Pipeline:
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|------------|:-------:|:--------:|:----------:|:--------:|
| image | 103.377 | 209.701 | 318.407 | 428.659 |
| resize | 20.121 | 88.308 | 161.366 | 234.437 |
| fir rust | 13.742 | 70.499 | 100.809 | 133.927 |
| fir sse4.1 | 12.031 | 23.732 | 30.216 | 37.862 |
| fir avx2 | 6.894 | 15.442 | 18.875 | 24.157 |
| image | 101.499 | 216.029 | 335.151 | 455.582 |
| resize | 19.671 | 85.199 | 155.205 | 224.660 |
| fir rust | 13.583 | 67.031 | 94.816 | 124.344 |
| fir sse4.1 | 12.012 | 23.370 | 29.345 | 36.925 |
| fir avx2 | 6.893 | 15.162 | 18.959 | 24.518 |
Compiled with `rustflags = ["-C", "target-cpu=native"]`
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|------------|:-------:|:--------:|:----------:|:--------:|
| image | 91.512 | 186.247 | 289.125 | 399.234 |
| resize | 20.377 | 74.147 | 139.552 | 205.352 |
| fir rust | 9.944 | 65.808 | 72.315 | 94.223 |
| fir sse4.1 | 7.838 | 18.97 | 24.053 | 31.164 |
| fir avx2 | 6.866 | 15.158 | 18.259 | 23.687 |
| image | 90.750 | 186.545 | 284.383 | 392.403 |
| resize | 19.918 | 69.129 | 130.433 | 191.987 |
| fir rust | 9.957 | 68.817 | 76.454 | 103.521 |
| fir sse4.1 | 7.865 | 18.407 | 23.586 | 30.649 |
| fir avx2 | 6.882 | 14.847 | 18.026 | 23.450 |
## Examples of code
+16 -15
View File
@@ -15,17 +15,16 @@ pub fn bench_downscale_rgb(bench: &mut Bench) {
let new_width = NonZeroU32::new(852).unwrap();
let new_height = NonZeroU32::new(567).unwrap();
// let mut group = c.benchmark_group("Downscale RGB (4928x3279 => 852x567)");
let alg_names = ["nearest", "triangle", "catmulrom", "lanczos3"];
let alg_names = ["Nearest", "Bilinear", "CatmullRom", "Lanczos3"];
// image crate
// https://crates.io/crates/image
for alg_name in alg_names {
let filter = match alg_name {
"nearest" => imageops::Nearest,
"triangle" => imageops::Triangle,
"catmulrom" => imageops::CatmullRom,
"lanczos3" => imageops::Lanczos3,
"Nearest" => imageops::Nearest,
"Bilinear" => imageops::Triangle,
"CatmullRom" => imageops::CatmullRom,
"Lanczos3" => imageops::Lanczos3,
_ => continue,
};
bench.task(format!("image - {}", alg_name), |task| {
@@ -42,10 +41,10 @@ pub fn bench_downscale_rgb(bench: &mut Bench) {
let mut dst = vec![RGB::new(0, 0, 0); (new_width.get() * new_height.get()) as usize];
bench.task(format!("resize - {}", alg_name), |task| {
let filter = match alg_name {
"nearest" => resize::Type::Point,
"triangle" => resize::Type::Triangle,
"catmulrom" => resize::Type::Catrom,
"lanczos3" => resize::Type::Lanczos3,
"Nearest" => resize::Type::Point,
"Bilinear" => resize::Type::Triangle,
"CatmullRom" => resize::Type::Catrom,
"Lanczos3" => resize::Type::Lanczos3,
_ => return,
};
let mut resize = resize::new(
@@ -94,10 +93,10 @@ pub fn bench_downscale_rgb(bench: &mut Bench) {
let mut dst_view = dst_image.dst_view();
let resize_alg = match alg_name {
"nearest" => ResizeAlg::Nearest,
"triangle" => ResizeAlg::Convolution(FilterType::Bilinear),
"catmulrom" => ResizeAlg::Convolution(FilterType::CatmulRom),
"lanczos3" => ResizeAlg::Convolution(FilterType::Lanczos3),
"Nearest" => ResizeAlg::Nearest,
"Bilinear" => ResizeAlg::Convolution(FilterType::Bilinear),
"CatmullRom" => ResizeAlg::Convolution(FilterType::CatmulRom),
"Lanczos3" => ResizeAlg::Convolution(FilterType::Lanczos3),
_ => return,
};
let mut fast_resizer = Resizer::new(resize_alg);
@@ -114,6 +113,8 @@ pub fn bench_downscale_rgb(bench: &mut Bench) {
});
}
}
utils::print_md_table(bench);
}
glassbench!("Compare", bench_downscale_rgb,);
glassbench!("Compare resize of RGB image", bench_downscale_rgb,);
+16 -15
View File
@@ -16,17 +16,16 @@ pub fn bench_downscale_rgba(bench: &mut Bench) {
let new_width = NonZeroU32::new(852).unwrap();
let new_height = NonZeroU32::new(567).unwrap();
// let mut group = c.benchmark_group("Downscale RGB (4928x3279 => 852x567)");
let alg_names = ["nearest", "triangle", "catmulrom", "lanczos3"];
let alg_names = ["Nearest", "Bilinear", "CatmullRom", "Lanczos3"];
// image crate
// https://crates.io/crates/image
for alg_name in alg_names {
let filter = match alg_name {
"nearest" => imageops::Nearest,
"triangle" => imageops::Triangle,
"catmulrom" => imageops::CatmullRom,
"lanczos3" => imageops::Lanczos3,
"Nearest" => imageops::Nearest,
"Bilinear" => imageops::Triangle,
"CatmullRom" => imageops::CatmullRom,
"Lanczos3" => imageops::Lanczos3,
_ => continue,
};
bench.task(format!("image - {}", alg_name), |task| {
@@ -43,10 +42,10 @@ pub fn bench_downscale_rgba(bench: &mut Bench) {
let mut dst = vec![RGBA::new(0, 0, 0, 0); (new_width.get() * new_height.get()) as usize];
bench.task(format!("resize - {}", alg_name), |task| {
let filter = match alg_name {
"nearest" => resize::Type::Point,
"triangle" => resize::Type::Triangle,
"catmulrom" => resize::Type::Catrom,
"lanczos3" => resize::Type::Lanczos3,
"Nearest" => resize::Type::Point,
"Bilinear" => resize::Type::Triangle,
"CatmullRom" => resize::Type::Catrom,
"Lanczos3" => resize::Type::Lanczos3,
_ => return,
};
let mut resize = resize::new(
@@ -78,10 +77,10 @@ pub fn bench_downscale_rgba(bench: &mut Bench) {
};
for alg_name in alg_names {
let resize_alg = match alg_name {
"nearest" => ResizeAlg::Nearest,
"triangle" => ResizeAlg::Convolution(FilterType::Bilinear),
"catmulrom" => ResizeAlg::Convolution(FilterType::CatmulRom),
"lanczos3" => ResizeAlg::Convolution(FilterType::Lanczos3),
"Nearest" => ResizeAlg::Nearest,
"Bilinear" => ResizeAlg::Convolution(FilterType::Bilinear),
"CatmullRom" => ResizeAlg::Convolution(FilterType::CatmulRom),
"Lanczos3" => ResizeAlg::Convolution(FilterType::Lanczos3),
_ => return,
};
let buf: Vec<u32> = src_image
@@ -125,6 +124,8 @@ pub fn bench_downscale_rgba(bench: &mut Bench) {
});
}
}
utils::print_md_table(bench);
}
glassbench!("Compare", bench_downscale_rgba,);
glassbench!("Compare resize of RGBA image", bench_downscale_rgba,);
+74
View File
@@ -1,5 +1,7 @@
use std::collections::HashMap;
use std::env;
use glassbench::*;
use image::io::Reader;
use image::{RgbImage, RgbaImage};
@@ -29,3 +31,75 @@ pub fn get_small_rgba_image() -> RgbaImage {
.unwrap();
img.to_rgba8()
}
pub fn print_md_table(bench: &Bench) {
let mut res_map: HashMap<String, Vec<String>> = HashMap::new();
let mut crate_names: Vec<String> = Vec::new();
let mut alg_names: Vec<String> = Vec::new();
for task in bench.tasks.iter() {
if let Some(measure) = task.measure {
let parts: Vec<&str> = task.name.split('-').map(|s| s.trim()).collect();
let crate_name = parts[0].to_string();
let alg_name = parts[1].to_string();
let value = measure.total_duration.as_secs_f64() * 1000. / measure.iterations as f64;
if !crate_names.contains(&crate_name) {
crate_names.push(crate_name.clone());
}
if !alg_names.contains(&alg_name) {
alg_names.push(alg_name);
}
if !res_map.contains_key(&crate_name) {
res_map.insert(crate_name.clone(), Vec::new());
}
if let Some(values) = res_map.get_mut(&crate_name) {
values.push(format!("{:.3}", value));
}
}
}
let first_column_width = res_map.keys().map(|s| s.len()).max().unwrap_or(0);
let mut column_width: Vec<usize> = vec![first_column_width];
for (i, name) in alg_names.iter().enumerate() {
let width = res_map.values().map(|v| v[i].len()).max().unwrap_or(0);
column_width.push(width.max(name.len()));
}
let mut first_row: Vec<String> = vec!["".to_owned()];
alg_names.iter().for_each(|s| first_row.push(s.to_owned()));
print_row(&column_width, &first_row);
print_header_underline(&column_width);
for name in crate_names.iter() {
if let Some(values) = res_map.get(name) {
let mut row = vec![name.clone()];
values.iter().for_each(|s| row.push(s.clone()));
print_row(&column_width, &row);
}
}
}
fn print_row(widths: &[usize], values: &[String]) {
for (i, (&width, value)) in widths.iter().zip(values).enumerate() {
if i == 0 {
print!("| {:width$} ", value, width = width);
} else {
print!("| {:^width$} ", value, width = width);
}
}
println!("|");
}
fn print_header_underline(widths: &[usize]) {
for (i, &width) in widths.iter().enumerate() {
if i == 0 {
print!("|{:-<width$}", "", width = width + 2);
} else {
print!("|:{:-<width$}:", "", width = width);
}
}
println!("|");
}
+3 -3
View File
@@ -5,11 +5,11 @@ use crate::convolution::{Bound, Coefficients, CoefficientsChunk, Convolution};
use crate::image_view::{DstImageView, FourRows, FourRowsMut, SrcImageView};
use crate::{optimisations, simd_utils};
pub struct Avx2;
pub struct Avx2U8x4;
// This code is based on C-implementation from Pillow-SIMD package for Python
// https://github.com/uploadcare/pillow-simd
impl Avx2 {
impl Avx2U8x4 {
/// For safety, it is necessary to ensure the following conditions:
/// - length of all rows in src_rows must be equal
/// - length of all rows in dst_rows must be equal
@@ -464,7 +464,7 @@ impl Avx2 {
}
}
impl Convolution for Avx2 {
impl Convolution for Avx2U8x4 {
#[inline]
fn horiz_convolution(
&self,
+2 -2
View File
@@ -1,9 +1,9 @@
use std::num::NonZeroU32;
pub use avx2::Avx2;
pub use avx2::Avx2U8x4;
pub use filters::{get_filter_func, FilterType};
pub use native::{NativeF32, NativeI32, NativeU8x4};
pub use sse4::Sse4;
pub use sse4::Sse4U8x4;
use crate::image_view::{DstImageView, SrcImageView};
+3 -3
View File
@@ -5,11 +5,11 @@ use crate::convolution::{Bound, Coefficients, CoefficientsChunk, Convolution};
use crate::image_view::{DstImageView, FourRows, FourRowsMut, SrcImageView};
use crate::{optimisations, simd_utils};
pub struct Sse4;
pub struct Sse4U8x4;
// This code is based on C-implementation from Pillow-SIMD package for Python
// https://github.com/uploadcare/pillow-simd
impl Sse4 {
impl Sse4U8x4 {
/// For safety, it is necessary to ensure the following conditions:
/// - length of all rows in src_rows must be equal
/// - length of all rows in dst_rows must be equal
@@ -484,7 +484,7 @@ impl Sse4 {
}
}
impl Convolution for Sse4 {
impl Convolution for Sse4U8x4 {
#[inline]
fn horiz_convolution(
&self,
+2 -2
View File
@@ -31,8 +31,8 @@ impl CpuExtensions {
fn get_resampler(&self, pixel_type: PixelType) -> &dyn Convolution {
match pixel_type {
PixelType::U8x4 => match self {
Self::Sse4_1 => &convolution::Sse4,
Self::Avx2 => &convolution::Avx2,
Self::Sse4_1 => &convolution::Sse4U8x4,
Self::Avx2 => &convolution::Avx2U8x4,
_ => &convolution::NativeU8x4,
},
PixelType::I32 => &convolution::NativeI32,
-10
View File
@@ -98,16 +98,6 @@ fn resample_sse4_lanczos3_test() {
save_result(&result.src_view(), "lanczos3_sse4");
}
fn resize_lanczos3(src_pixels: &[u32], width: NonZeroU32, height: NonZeroU32) -> Vec<u32> {
let src_image = ImageData::new(width, height, src_pixels, PixelType::U8x4).unwrap();
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
let dst_width = NonZeroU32::new(1024).unwrap();
let dst_height = NonZeroU32::new(768).unwrap();
let mut dst_image = ImageData::new_owned(dst_width, dst_height, src_image.pixel_type());
resizer.resize(&src_image.src_view(), &mut dst_image.dst_view());
dst_image.get_pixels().to_owned()
}
#[test]
fn resample_avx2_lanczos3_test() {
let image = get_source_image();