mirror of
https://github.com/Cykooz/fast_image_resize.git
synced 2026-10-08 01:11:09 +00:00
criterion replaced by glassbench.
This commit is contained in:
Generated
+575
-215
File diff suppressed because it is too large
Load Diff
+7
-2
@@ -18,7 +18,7 @@ thiserror = "1.0.26"
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.3.4"
|
||||
glassbench = "0.3.0"
|
||||
image = "0.23.14"
|
||||
resize = "0.7.0"
|
||||
rgb = "0.8.25"
|
||||
@@ -35,7 +35,12 @@ harness = false
|
||||
|
||||
|
||||
[[bench]]
|
||||
name = "bench_compare"
|
||||
name = "bench_compare_rgb"
|
||||
harness = false
|
||||
|
||||
|
||||
[[bench]]
|
||||
name = "bench_compare_rgba"
|
||||
harness = false
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ Environment:
|
||||
- RAM: DDR4 3000 MHz
|
||||
- Ubuntu 20.04 (linux 5.8)
|
||||
- fast_image_resize = "0.1"
|
||||
- criterion = "0.3.4"
|
||||
- glassbench = "0.3.0"
|
||||
|
||||
Other Rust libraries used to compare of resizing speed:
|
||||
- image = "0.23.14" (https://crates.io/crates/image)
|
||||
@@ -40,25 +40,25 @@ Pipeline:
|
||||
`src_image => resize => dst_image`
|
||||
|
||||
- Source image [nasa-4928x3279.png](https://github.com/Cykooz/fast_image_resize/blob/main/data/nasa-4928x3279.png)
|
||||
- Numbers in table is time of image resizing in milliseconds.
|
||||
- Numbers in table is mean duration of image resizing in milliseconds.
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| image | 105.38 | 204.21 | 301.58 | 399.52 |
|
||||
| resize | 16.223 | 72.447 | 132.64 | 193.26 |
|
||||
| fir rust | 0.476 | 57.003 | 87.564 | 120.65 |
|
||||
| fir sse4.1 | - | 12.143 | 18.662 | 26.334 |
|
||||
| fir avx2 | - | 9.346 | 13.342 | 18.934 |
|
||||
| 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 |
|
||||
|
||||
Compiled with `rustflags = ["-C", "target-cpu=native"]`
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| image | 91.498 | 183.47 | 282.34 | 386.74 |
|
||||
| resize | 15.752 | 63.137 | 116.45 | 169.73 |
|
||||
| fir rust | 0.467 | 58.133 | 65.575 | 89.721 |
|
||||
| fir sse4.1 | - | 11.567 | 16.566 | 23.859 |
|
||||
| fir avx2 | - | 8.746 | 11.818 | 17.253 |
|
||||
| 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 |
|
||||
|
||||
### Resize RGBA image 4928x3279 => 852x567
|
||||
|
||||
@@ -67,25 +67,25 @@ Pipeline:
|
||||
`src_image => multiply by alpha => resize => divide by alpha => dst_image`
|
||||
|
||||
- Source image [nasa-4928x3279.png](https://github.com/Cykooz/fast_image_resize/blob/main/data/nasa-4928x3279.png)
|
||||
- Numbers in table is time of image resizing in milliseconds.
|
||||
- Numbers in table is mean duration of image resizing in milliseconds.
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| image | 110.45 | 264.84 | 421.25 | 596.17 |
|
||||
| resize | 23.919 | 100.38 | 173.62 | 247.39 |
|
||||
| fir rust | 13.832 | 70.448 | 100.87 | 133.84 |
|
||||
| fir sse4.1 | 12.03 | 23.721 | 30.266 | 37.874 |
|
||||
| fir avx2 | 6.949 | 15.873 | 19.956 | 25.527 |
|
||||
| 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 |
|
||||
|
||||
Compiled with `rustflags = ["-C", "target-cpu=native"]`
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| image | 97.782 | 246.27 | 403.20 | 568.91 |
|
||||
| resize | 24.282 | 86.244 | 151.41 | 217.74 |
|
||||
| fir rust | 9.968 | 67.628 | 74.96 | 99.376 |
|
||||
| fir sse4.1 | 7.926 | 19.017 | 24.06 | 31.323 |
|
||||
| fir avx2 | 6.924 | 15.312 | 18.266 | 23.703 |
|
||||
| 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 |
|
||||
|
||||
## Examples of code
|
||||
|
||||
|
||||
+23
-23
@@ -1,7 +1,8 @@
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use glassbench::*;
|
||||
|
||||
use fast_image_resize::{CpuExtensions, ImageData, MulDiv, PixelType};
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
const fn p(r: u8, g: u8, b: u8, a: u8) -> u32 {
|
||||
u32::from_le_bytes([r, g, b, a])
|
||||
@@ -22,7 +23,7 @@ fn get_src_image(width: NonZeroU32, height: NonZeroU32, pixel: u32) -> ImageData
|
||||
ImageData::new(width, height, buffer, PixelType::U8x4).unwrap()
|
||||
}
|
||||
|
||||
fn multiplies_alpha_avx2(c: &mut Criterion) {
|
||||
fn multiplies_alpha_avx2(bench: &mut Bench) {
|
||||
let width = NonZeroU32::new(4096).unwrap();
|
||||
let height = NonZeroU32::new(2048).unwrap();
|
||||
let src_data = get_src_image(width, height, p(255, 128, 0, 128));
|
||||
@@ -34,8 +35,8 @@ fn multiplies_alpha_avx2(c: &mut Criterion) {
|
||||
alpha_mul_div.set_cpu_extensions(CpuExtensions::Avx2);
|
||||
}
|
||||
|
||||
c.bench_function("Multiplies alpha AVX2", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("Multiplies alpha AVX2", |task| {
|
||||
task.iter(|| {
|
||||
alpha_mul_div
|
||||
.multiply_alpha(&src_view, &mut dst_view)
|
||||
.unwrap();
|
||||
@@ -43,7 +44,7 @@ fn multiplies_alpha_avx2(c: &mut Criterion) {
|
||||
});
|
||||
}
|
||||
|
||||
fn multiplies_alpha_sse2(c: &mut Criterion) {
|
||||
fn multiplies_alpha_sse2(bench: &mut Bench) {
|
||||
let width = NonZeroU32::new(4096).unwrap();
|
||||
let height = NonZeroU32::new(2048).unwrap();
|
||||
let src_data = get_src_image(width, height, p(255, 128, 0, 128));
|
||||
@@ -55,8 +56,8 @@ fn multiplies_alpha_sse2(c: &mut Criterion) {
|
||||
alpha_mul_div.set_cpu_extensions(CpuExtensions::Sse2);
|
||||
}
|
||||
|
||||
c.bench_function("Multiplies alpha SSE2", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("Multiplies alpha SSE2", |task| {
|
||||
task.iter(|| {
|
||||
alpha_mul_div
|
||||
.multiply_alpha(&src_view, &mut dst_view)
|
||||
.unwrap();
|
||||
@@ -64,7 +65,7 @@ fn multiplies_alpha_sse2(c: &mut Criterion) {
|
||||
});
|
||||
}
|
||||
|
||||
fn multiplies_alpha_native(c: &mut Criterion) {
|
||||
fn multiplies_alpha_native(bench: &mut Bench) {
|
||||
let width = NonZeroU32::new(4096).unwrap();
|
||||
let height = NonZeroU32::new(2048).unwrap();
|
||||
let src_data = get_src_image(width, height, p(255, 128, 0, 128));
|
||||
@@ -76,8 +77,8 @@ fn multiplies_alpha_native(c: &mut Criterion) {
|
||||
alpha_mul_div.set_cpu_extensions(CpuExtensions::None);
|
||||
}
|
||||
|
||||
c.bench_function("Multiplies alpha native", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("Multiplies alpha native", |task| {
|
||||
task.iter(|| {
|
||||
alpha_mul_div
|
||||
.multiply_alpha(&src_view, &mut dst_view)
|
||||
.unwrap();
|
||||
@@ -85,7 +86,7 @@ fn multiplies_alpha_native(c: &mut Criterion) {
|
||||
});
|
||||
}
|
||||
|
||||
fn divides_alpha_avx2(c: &mut Criterion) {
|
||||
fn divides_alpha_avx2(bench: &mut Bench) {
|
||||
let width = NonZeroU32::new(4096).unwrap();
|
||||
let height = NonZeroU32::new(2048).unwrap();
|
||||
let src_data = get_src_image(width, height, p(128, 64, 0, 128));
|
||||
@@ -97,8 +98,8 @@ fn divides_alpha_avx2(c: &mut Criterion) {
|
||||
alpha_mul_div.set_cpu_extensions(CpuExtensions::Avx2);
|
||||
}
|
||||
|
||||
c.bench_function("Divides alpha AVX2", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("Divides alpha AVX2", |task| {
|
||||
task.iter(|| {
|
||||
alpha_mul_div
|
||||
.divide_alpha(&src_view, &mut dst_view)
|
||||
.unwrap();
|
||||
@@ -106,7 +107,7 @@ fn divides_alpha_avx2(c: &mut Criterion) {
|
||||
});
|
||||
}
|
||||
|
||||
fn divides_alpha_sse2(c: &mut Criterion) {
|
||||
fn divides_alpha_sse2(bench: &mut Bench) {
|
||||
let width = NonZeroU32::new(4096).unwrap();
|
||||
let height = NonZeroU32::new(2048).unwrap();
|
||||
let src_data = get_src_image(width, height, p(128, 64, 0, 128));
|
||||
@@ -118,8 +119,8 @@ fn divides_alpha_sse2(c: &mut Criterion) {
|
||||
alpha_mul_div.set_cpu_extensions(CpuExtensions::Sse2);
|
||||
}
|
||||
|
||||
c.bench_function("Divides alpha SSE2", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("Divides alpha SSE2", |task| {
|
||||
task.iter(|| {
|
||||
alpha_mul_div
|
||||
.divide_alpha(&src_view, &mut dst_view)
|
||||
.unwrap();
|
||||
@@ -127,7 +128,7 @@ fn divides_alpha_sse2(c: &mut Criterion) {
|
||||
});
|
||||
}
|
||||
|
||||
fn divides_alpha_native(c: &mut Criterion) {
|
||||
fn divides_alpha_native(bench: &mut Bench) {
|
||||
let width = NonZeroU32::new(4096).unwrap();
|
||||
let height = NonZeroU32::new(2048).unwrap();
|
||||
let src_data = get_src_image(width, height, p(128, 64, 0, 128));
|
||||
@@ -139,8 +140,8 @@ fn divides_alpha_native(c: &mut Criterion) {
|
||||
alpha_mul_div.set_cpu_extensions(CpuExtensions::None);
|
||||
}
|
||||
|
||||
c.bench_function("Divides alpha native", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("Divides alpha native", |task| {
|
||||
task.iter(|| {
|
||||
alpha_mul_div
|
||||
.divide_alpha(&src_view, &mut dst_view)
|
||||
.unwrap();
|
||||
@@ -148,8 +149,8 @@ fn divides_alpha_native(c: &mut Criterion) {
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
glassbench!(
|
||||
"Alpha",
|
||||
multiplies_alpha_avx2,
|
||||
multiplies_alpha_sse2,
|
||||
multiplies_alpha_native,
|
||||
@@ -157,4 +158,3 @@ criterion_group!(
|
||||
divides_alpha_sse2,
|
||||
divides_alpha_native,
|
||||
);
|
||||
criterion_main!(benches);
|
||||
|
||||
@@ -1,315 +0,0 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use image::imageops;
|
||||
use resize::px::RGBA;
|
||||
use resize::Pixel::{RGB8, RGBA8};
|
||||
use rgb::{FromSlice, RGB};
|
||||
|
||||
use fast_image_resize::{CpuExtensions, FilterType, PixelType, ResizeAlg, Resizer};
|
||||
use fast_image_resize::{ImageData, MulDiv};
|
||||
|
||||
mod utils;
|
||||
|
||||
pub fn bench_downscale_rgb(c: &mut Criterion) {
|
||||
let src_image = utils::get_big_rgb_image();
|
||||
let new_width = NonZeroU32::new(852).unwrap();
|
||||
let new_height = NonZeroU32::new(567).unwrap();
|
||||
|
||||
let mut group = c.benchmark_group("Downscale RGB (4928x3279 => 852x567)");
|
||||
|
||||
for alg_num in 0..4 {
|
||||
// image crate
|
||||
// https://crates.io/crates/image
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("image", alg_num),
|
||||
&alg_num,
|
||||
|b, alg_num| {
|
||||
b.iter(|| {
|
||||
let filter = match alg_num {
|
||||
0 => imageops::Nearest,
|
||||
1 => imageops::Triangle,
|
||||
2 => imageops::CatmullRom,
|
||||
3 => imageops::Lanczos3,
|
||||
_ => return,
|
||||
};
|
||||
imageops::resize(&src_image, new_width.get(), new_height.get(), filter);
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
// resize crate
|
||||
// https://crates.io/crates/resize
|
||||
let resize_src_image = src_image.as_raw().as_rgb();
|
||||
let mut dst = vec![RGB::new(0, 0, 0); (new_width.get() * new_height.get()) as usize];
|
||||
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("resize", alg_num),
|
||||
&alg_num,
|
||||
|b, alg_num| {
|
||||
let filter = match alg_num {
|
||||
0 => resize::Type::Point,
|
||||
1 => resize::Type::Triangle,
|
||||
2 => resize::Type::Catrom,
|
||||
3 => resize::Type::Lanczos3,
|
||||
_ => return,
|
||||
};
|
||||
let mut resizer = resize::new(
|
||||
src_image.width() as usize,
|
||||
src_image.height() as usize,
|
||||
new_width.get() as usize,
|
||||
new_height.get() as usize,
|
||||
RGB8,
|
||||
filter,
|
||||
)
|
||||
.unwrap();
|
||||
b.iter(|| {
|
||||
resizer.resize(resize_src_image, &mut dst).unwrap();
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
// fast_image_resize crate;
|
||||
let src_rgba_image = utils::get_big_rgba_image();
|
||||
let src_image_data = ImageData::new(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
src_rgba_image.as_raw(),
|
||||
PixelType::U8x4,
|
||||
)
|
||||
.unwrap();
|
||||
let src_view = src_image_data.src_view();
|
||||
let mut dst_image = ImageData::new_owned(new_width, new_height, PixelType::U8x4);
|
||||
let mut dst_view = dst_image.dst_view();
|
||||
let mut fast_resizer = Resizer::new(ResizeAlg::Nearest);
|
||||
unsafe {
|
||||
fast_resizer.set_cpu_extensions(CpuExtensions::None);
|
||||
}
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("fast_wo_simd", alg_num),
|
||||
&alg_num,
|
||||
|b, alg_num| {
|
||||
let resize_alg = match alg_num {
|
||||
0 => ResizeAlg::Nearest,
|
||||
1 => ResizeAlg::Convolution(FilterType::Bilinear),
|
||||
2 => ResizeAlg::Convolution(FilterType::CatmulRom),
|
||||
3 => ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
_ => return,
|
||||
};
|
||||
fast_resizer.algorithm = resize_alg;
|
||||
b.iter(|| {
|
||||
fast_resizer.resize(&src_view, &mut dst_view);
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
let mut fast_resizer = Resizer::new(ResizeAlg::Nearest);
|
||||
unsafe {
|
||||
fast_resizer.set_cpu_extensions(CpuExtensions::Sse4_1);
|
||||
}
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("fast_sse4", alg_num),
|
||||
&alg_num,
|
||||
|b, alg_num| {
|
||||
let resize_alg = match alg_num {
|
||||
0 => ResizeAlg::Nearest,
|
||||
1 => ResizeAlg::Convolution(FilterType::Bilinear),
|
||||
2 => ResizeAlg::Convolution(FilterType::CatmulRom),
|
||||
3 => ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
_ => return,
|
||||
};
|
||||
fast_resizer.algorithm = resize_alg;
|
||||
b.iter(|| {
|
||||
fast_resizer.resize(&src_view, &mut dst_view);
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
let mut fast_resizer = Resizer::new(ResizeAlg::Nearest);
|
||||
unsafe {
|
||||
fast_resizer.set_cpu_extensions(CpuExtensions::Avx2);
|
||||
}
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("fast_avx2", alg_num),
|
||||
&alg_num,
|
||||
|b, alg_num| {
|
||||
let resize_alg = match alg_num {
|
||||
0 => ResizeAlg::Nearest,
|
||||
1 => ResizeAlg::Convolution(FilterType::Bilinear),
|
||||
2 => ResizeAlg::Convolution(FilterType::CatmulRom),
|
||||
3 => ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
_ => return,
|
||||
};
|
||||
fast_resizer.algorithm = resize_alg;
|
||||
b.iter(|| {
|
||||
fast_resizer.resize(&src_view, &mut dst_view);
|
||||
})
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
pub fn bench_downscale_rgba(c: &mut Criterion) {
|
||||
let src_image = utils::get_big_rgba_image();
|
||||
let new_width = NonZeroU32::new(852).unwrap();
|
||||
let new_height = NonZeroU32::new(567).unwrap();
|
||||
|
||||
let mut group = c.benchmark_group("Downscale RGBA (4928x3279 => 852x567)");
|
||||
|
||||
for alg_num in 0..4 {
|
||||
// image crate
|
||||
// https://crates.io/crates/image
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("image", alg_num),
|
||||
&alg_num,
|
||||
|b, alg_num| {
|
||||
b.iter(|| {
|
||||
let filter = match alg_num {
|
||||
0 => imageops::Nearest,
|
||||
1 => imageops::Triangle,
|
||||
2 => imageops::CatmullRom,
|
||||
3 => imageops::Lanczos3,
|
||||
_ => return,
|
||||
};
|
||||
imageops::resize(&src_image, new_width.get(), new_height.get(), filter);
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
// resize crate
|
||||
// https://crates.io/crates/resize
|
||||
let resize_src_image = src_image.as_raw().as_rgba();
|
||||
let mut dst = vec![RGBA::new(0, 0, 0, 0); (new_width.get() * new_height.get()) as usize];
|
||||
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("resize", alg_num),
|
||||
&alg_num,
|
||||
|b, alg_num| {
|
||||
let filter = match alg_num {
|
||||
0 => resize::Type::Point,
|
||||
1 => resize::Type::Triangle,
|
||||
2 => resize::Type::Catrom,
|
||||
3 => resize::Type::Lanczos3,
|
||||
_ => return,
|
||||
};
|
||||
let mut resizer = resize::new(
|
||||
src_image.width() as usize,
|
||||
src_image.height() as usize,
|
||||
new_width.get() as usize,
|
||||
new_height.get() as usize,
|
||||
RGBA8,
|
||||
filter,
|
||||
)
|
||||
.unwrap();
|
||||
b.iter(|| {
|
||||
resizer.resize(resize_src_image, &mut dst).unwrap();
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
// fast_image_resize crate;
|
||||
let src_image_data = ImageData::new(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
src_image.as_raw(),
|
||||
PixelType::U8x4,
|
||||
)
|
||||
.unwrap();
|
||||
let src_view = src_image_data.src_view();
|
||||
let mut premultiplied_src_image = ImageData::new_owned(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
PixelType::U8x4,
|
||||
);
|
||||
let mut dst_image = ImageData::new_owned(new_width, new_height, PixelType::U8x4);
|
||||
let mut dst_view = dst_image.dst_view();
|
||||
let mut fast_resizer = Resizer::new(ResizeAlg::Nearest);
|
||||
let mut mul_div = MulDiv::default();
|
||||
unsafe {
|
||||
fast_resizer.set_cpu_extensions(CpuExtensions::None);
|
||||
mul_div.set_cpu_extensions(CpuExtensions::None);
|
||||
}
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("fast_wo_simd", alg_num),
|
||||
&alg_num,
|
||||
|b, alg_num| {
|
||||
let resize_alg = match alg_num {
|
||||
0 => ResizeAlg::Nearest,
|
||||
1 => ResizeAlg::Convolution(FilterType::Bilinear),
|
||||
2 => ResizeAlg::Convolution(FilterType::CatmulRom),
|
||||
3 => ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
_ => return,
|
||||
};
|
||||
fast_resizer.algorithm = resize_alg;
|
||||
b.iter(|| {
|
||||
mul_div
|
||||
.multiply_alpha(&src_view, &mut premultiplied_src_image.dst_view())
|
||||
.unwrap();
|
||||
fast_resizer.resize(&premultiplied_src_image.src_view(), &mut dst_view);
|
||||
mul_div.divide_alpha_inplace(&mut dst_view).unwrap();
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
let mut fast_resizer = Resizer::new(ResizeAlg::Nearest);
|
||||
unsafe {
|
||||
fast_resizer.set_cpu_extensions(CpuExtensions::Sse4_1);
|
||||
mul_div.set_cpu_extensions(CpuExtensions::Sse4_1);
|
||||
}
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("fast_sse4", alg_num),
|
||||
&alg_num,
|
||||
|b, alg_num| {
|
||||
let resize_alg = match alg_num {
|
||||
0 => ResizeAlg::Nearest,
|
||||
1 => ResizeAlg::Convolution(FilterType::Bilinear),
|
||||
2 => ResizeAlg::Convolution(FilterType::CatmulRom),
|
||||
3 => ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
_ => return,
|
||||
};
|
||||
fast_resizer.algorithm = resize_alg;
|
||||
b.iter(|| {
|
||||
mul_div
|
||||
.multiply_alpha(&src_view, &mut premultiplied_src_image.dst_view())
|
||||
.unwrap();
|
||||
fast_resizer.resize(&premultiplied_src_image.src_view(), &mut dst_view);
|
||||
mul_div.divide_alpha_inplace(&mut dst_view).unwrap();
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
let mut fast_resizer = Resizer::new(ResizeAlg::Nearest);
|
||||
unsafe {
|
||||
fast_resizer.set_cpu_extensions(CpuExtensions::Avx2);
|
||||
mul_div.set_cpu_extensions(CpuExtensions::Avx2);
|
||||
}
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("fast_avx2", alg_num),
|
||||
&alg_num,
|
||||
|b, alg_num| {
|
||||
let resize_alg = match alg_num {
|
||||
0 => ResizeAlg::Nearest,
|
||||
1 => ResizeAlg::Convolution(FilterType::Bilinear),
|
||||
2 => ResizeAlg::Convolution(FilterType::CatmulRom),
|
||||
3 => ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
_ => return,
|
||||
};
|
||||
fast_resizer.algorithm = resize_alg;
|
||||
b.iter(|| {
|
||||
mul_div
|
||||
.multiply_alpha(&src_view, &mut premultiplied_src_image.dst_view())
|
||||
.unwrap();
|
||||
fast_resizer.resize(&premultiplied_src_image.src_view(), &mut dst_view);
|
||||
mul_div.divide_alpha_inplace(&mut dst_view).unwrap();
|
||||
})
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_downscale_rgb, bench_downscale_rgba);
|
||||
criterion_main!(benches);
|
||||
@@ -0,0 +1,114 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use glassbench::*;
|
||||
use image::imageops;
|
||||
use resize::Pixel::RGB8;
|
||||
use rgb::{FromSlice, RGB};
|
||||
|
||||
use fast_image_resize::ImageData;
|
||||
use fast_image_resize::{CpuExtensions, FilterType, PixelType, ResizeAlg, Resizer};
|
||||
|
||||
mod utils;
|
||||
|
||||
pub fn bench_downscale_rgb(bench: &mut Bench) {
|
||||
let src_image = utils::get_big_rgb_image();
|
||||
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"];
|
||||
|
||||
// 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,
|
||||
_ => continue,
|
||||
};
|
||||
bench.task(format!("image - {}", alg_name), |task| {
|
||||
task.iter(|| {
|
||||
imageops::resize(&src_image, new_width.get(), new_height.get(), filter);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// resize crate
|
||||
// https://crates.io/crates/resize
|
||||
for alg_name in alg_names {
|
||||
let resize_src_image = src_image.as_raw().as_rgb();
|
||||
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,
|
||||
_ => return,
|
||||
};
|
||||
let mut resize = resize::new(
|
||||
src_image.width() as usize,
|
||||
src_image.height() as usize,
|
||||
new_width.get() as usize,
|
||||
new_height.get() as usize,
|
||||
RGB8,
|
||||
filter,
|
||||
)
|
||||
.unwrap();
|
||||
task.iter(|| {
|
||||
resize.resize(resize_src_image, &mut dst).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// fast_image_resize crate;
|
||||
for cpu_ext in [
|
||||
CpuExtensions::None,
|
||||
CpuExtensions::Sse4_1,
|
||||
CpuExtensions::Avx2,
|
||||
] {
|
||||
let ext_name = match cpu_ext {
|
||||
CpuExtensions::None => "rust",
|
||||
CpuExtensions::Sse4_1 => "sse4.1",
|
||||
CpuExtensions::Avx2 => "avx2",
|
||||
_ => continue,
|
||||
};
|
||||
for alg_name in alg_names {
|
||||
let src_rgba_image = utils::get_big_rgba_image();
|
||||
let src_image_data = ImageData::new(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
src_rgba_image.as_raw(),
|
||||
PixelType::U8x4,
|
||||
)
|
||||
.unwrap();
|
||||
let src_view = src_image_data.src_view();
|
||||
let mut dst_image = ImageData::new_owned(new_width, new_height, PixelType::U8x4);
|
||||
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),
|
||||
_ => return,
|
||||
};
|
||||
let mut fast_resizer = Resizer::new(resize_alg);
|
||||
|
||||
unsafe {
|
||||
fast_resizer.reset_internal_buffers();
|
||||
fast_resizer.set_cpu_extensions(cpu_ext);
|
||||
}
|
||||
|
||||
bench.task(format!("fir {} - {}", ext_name, alg_name), |task| {
|
||||
task.iter(|| {
|
||||
fast_resizer.resize(&src_view, &mut dst_view);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glassbench!("Compare", bench_downscale_rgb,);
|
||||
@@ -0,0 +1,125 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use glassbench::*;
|
||||
use image::imageops;
|
||||
use resize::px::RGBA;
|
||||
use resize::Pixel::RGBA8;
|
||||
use rgb::FromSlice;
|
||||
|
||||
use fast_image_resize::{CpuExtensions, FilterType, PixelType, ResizeAlg, Resizer};
|
||||
use fast_image_resize::{ImageData, MulDiv};
|
||||
|
||||
mod utils;
|
||||
|
||||
pub fn bench_downscale_rgba(bench: &mut Bench) {
|
||||
let src_image = utils::get_big_rgba_image();
|
||||
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"];
|
||||
|
||||
// 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,
|
||||
_ => continue,
|
||||
};
|
||||
bench.task(format!("image - {}", alg_name), |task| {
|
||||
task.iter(|| {
|
||||
imageops::resize(&src_image, new_width.get(), new_height.get(), filter);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// resize crate
|
||||
// https://crates.io/crates/resize
|
||||
for alg_name in alg_names {
|
||||
let resize_src_image = src_image.as_raw().as_rgba();
|
||||
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,
|
||||
_ => return,
|
||||
};
|
||||
let mut resize = resize::new(
|
||||
src_image.width() as usize,
|
||||
src_image.height() as usize,
|
||||
new_width.get() as usize,
|
||||
new_height.get() as usize,
|
||||
RGBA8,
|
||||
filter,
|
||||
)
|
||||
.unwrap();
|
||||
task.iter(|| {
|
||||
resize.resize(resize_src_image, &mut dst).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// fast_image_resize crate;
|
||||
for cpu_ext in [
|
||||
CpuExtensions::None,
|
||||
CpuExtensions::Sse4_1,
|
||||
CpuExtensions::Avx2,
|
||||
] {
|
||||
let ext_name = match cpu_ext {
|
||||
CpuExtensions::None => "rust",
|
||||
CpuExtensions::Sse4_1 => "sse4.1",
|
||||
CpuExtensions::Avx2 => "avx2",
|
||||
_ => continue,
|
||||
};
|
||||
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),
|
||||
_ => return,
|
||||
};
|
||||
let src_image_data = ImageData::new(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
src_image.as_raw(),
|
||||
PixelType::U8x4,
|
||||
)
|
||||
.unwrap();
|
||||
let src_view = src_image_data.src_view();
|
||||
let mut premultiplied_src_image = ImageData::new_owned(
|
||||
NonZeroU32::new(src_image.width()).unwrap(),
|
||||
NonZeroU32::new(src_image.height()).unwrap(),
|
||||
PixelType::U8x4,
|
||||
);
|
||||
let mut dst_image = ImageData::new_owned(new_width, new_height, PixelType::U8x4);
|
||||
let mut dst_view = dst_image.dst_view();
|
||||
let mut mul_div = MulDiv::default();
|
||||
|
||||
let mut fast_resizer = Resizer::new(resize_alg);
|
||||
|
||||
unsafe {
|
||||
fast_resizer.reset_internal_buffers();
|
||||
fast_resizer.set_cpu_extensions(cpu_ext);
|
||||
mul_div.set_cpu_extensions(cpu_ext);
|
||||
}
|
||||
|
||||
bench.task(format!("fir {} - {}", ext_name, alg_name), |task| {
|
||||
task.iter(|| {
|
||||
mul_div
|
||||
.multiply_alpha(&src_view, &mut premultiplied_src_image.dst_view())
|
||||
.unwrap();
|
||||
fast_resizer.resize(&premultiplied_src_image.src_view(), &mut dst_view);
|
||||
mul_div.divide_alpha_inplace(&mut dst_view).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glassbench!("Compare", bench_downscale_rgba,);
|
||||
+27
-29
@@ -1,6 +1,6 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use glassbench::*;
|
||||
|
||||
use fast_image_resize::ImageData;
|
||||
use fast_image_resize::{CpuExtensions, FilterType, PixelType, ResizeAlg, Resizer};
|
||||
@@ -14,7 +14,7 @@ const NEW_BIG_WIDTH: u32 = 4928;
|
||||
const NEW_BIG_HEIGHT: u32 = 3279;
|
||||
|
||||
fn get_big_source_image() -> ImageData<Vec<u8>> {
|
||||
let img = utils::get_big_rgb_image();
|
||||
let img = utils::get_big_rgba_image();
|
||||
let width = img.width();
|
||||
let height = img.height();
|
||||
let buf = img.as_raw().clone();
|
||||
@@ -28,7 +28,7 @@ fn get_big_source_image() -> ImageData<Vec<u8>> {
|
||||
}
|
||||
|
||||
fn get_small_source_image() -> ImageData<Vec<u8>> {
|
||||
let img = utils::get_small_rgb_image();
|
||||
let img = utils::get_small_rgba_image();
|
||||
let width = img.width();
|
||||
let height = img.height();
|
||||
let buf = img.as_raw().clone();
|
||||
@@ -41,7 +41,7 @@ fn get_small_source_image() -> ImageData<Vec<u8>> {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn downscale_nearest_wo_simd_bench(c: &mut Criterion) {
|
||||
fn nearest_wo_simd_bench(bench: &mut Bench) {
|
||||
let image = get_big_source_image();
|
||||
let mut res_image = ImageData::new_owned(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
@@ -54,14 +54,14 @@ fn downscale_nearest_wo_simd_bench(c: &mut Criterion) {
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(CpuExtensions::None);
|
||||
}
|
||||
c.bench_function("Downscale nearest wo SIMD", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("nearest wo SIMD", |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn downscale_lanczos3_wo_simd_bench(c: &mut Criterion) {
|
||||
fn lanczos3_wo_simd_bench(bench: &mut Bench) {
|
||||
let image = get_big_source_image();
|
||||
let mut res_image = ImageData::new_owned(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
@@ -74,14 +74,14 @@ fn downscale_lanczos3_wo_simd_bench(c: &mut Criterion) {
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(CpuExtensions::None);
|
||||
}
|
||||
c.bench_function("Downscale lanczos3 wo SIMD", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("lanczos3 wo SIMD", |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn sse4_lanczos3_bench(c: &mut Criterion) {
|
||||
fn sse4_lanczos3_bench(bench: &mut Bench) {
|
||||
let image = get_big_source_image();
|
||||
let mut res_image = ImageData::new_owned(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
@@ -94,14 +94,14 @@ fn sse4_lanczos3_bench(c: &mut Criterion) {
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(CpuExtensions::Sse4_1);
|
||||
}
|
||||
c.bench_function("sse4 lanczos3", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("sse4 lanczos3", |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn avx2_lanczos3_bench(c: &mut Criterion) {
|
||||
fn avx2_lanczos3_bench(bench: &mut Bench) {
|
||||
let image = get_big_source_image();
|
||||
let mut res_image = ImageData::new_owned(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
@@ -114,14 +114,14 @@ fn avx2_lanczos3_bench(c: &mut Criterion) {
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(CpuExtensions::Avx2);
|
||||
}
|
||||
c.bench_function("avx2 lanczos3", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("avx2 lanczos3", |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn avx2_supersampling_lanczos3_bench(c: &mut Criterion) {
|
||||
fn avx2_supersampling_lanczos3_bench(bench: &mut Bench) {
|
||||
let image = get_big_source_image();
|
||||
let mut res_image = ImageData::new_owned(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
@@ -134,14 +134,14 @@ fn avx2_supersampling_lanczos3_bench(c: &mut Criterion) {
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(CpuExtensions::Avx2);
|
||||
}
|
||||
c.bench_function("avx2 supersampling lanczos3", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("avx2 supersampling lanczos3", |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn avx2_lanczos3_upscale_bench(c: &mut Criterion) {
|
||||
fn avx2_lanczos3_upscale_bench(bench: &mut Bench) {
|
||||
let image = get_small_source_image();
|
||||
let mut res_image = ImageData::new_owned(
|
||||
NonZeroU32::new(NEW_BIG_WIDTH).unwrap(),
|
||||
@@ -154,21 +154,19 @@ fn avx2_lanczos3_upscale_bench(c: &mut Criterion) {
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(CpuExtensions::Avx2);
|
||||
}
|
||||
c.bench_function("avx2 lanczos3 upscale", |b| {
|
||||
b.iter(|| {
|
||||
bench.task("avx2 lanczos3 upscale", |task| {
|
||||
task.iter(|| {
|
||||
resizer.resize(&src_image, &mut dst_image);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
// downscale_nearest_wo_simd_bench,
|
||||
downscale_lanczos3_wo_simd_bench,
|
||||
// resize_lanczos3_bench,
|
||||
glassbench!(
|
||||
"Resize",
|
||||
nearest_wo_simd_bench,
|
||||
lanczos3_wo_simd_bench,
|
||||
sse4_lanczos3_bench,
|
||||
avx2_lanczos3_bench,
|
||||
// avx2_supersampling_lanczos3_bench,
|
||||
// avx2_lanczos3_upscale_bench,
|
||||
avx2_supersampling_lanczos3_bench,
|
||||
avx2_lanczos3_upscale_bench,
|
||||
);
|
||||
criterion_main!(benches);
|
||||
|
||||
@@ -21,11 +21,11 @@ pub fn get_big_rgba_image() -> RgbaImage {
|
||||
img.to_rgba8()
|
||||
}
|
||||
|
||||
pub fn get_small_rgb_image() -> RgbImage {
|
||||
pub fn get_small_rgba_image() -> RgbaImage {
|
||||
let cur_dir = env::current_dir().unwrap();
|
||||
let img = Reader::open(cur_dir.join("data/nasa-852x567.png"))
|
||||
.unwrap()
|
||||
.decode()
|
||||
.unwrap();
|
||||
img.to_rgb8()
|
||||
img.to_rgba8()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user