-
-
Save CAD97/0157c14b640b678a30309c81e8e2b8d7 to your computer and use it in GitHub Desktop.
bgra_to_rgb benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use bgra_to_rgb::*; | |
use criterion::*; | |
use rand::{Rng, SeedableRng}; | |
use rand_chacha::ChaChaRng; | |
pub fn benchmark_move(c: &mut Criterion) { | |
// random bytes from random.org | |
let rand = ChaChaRng::from_seed([ | |
0x1c, 0xd7, 0x75, 0x38, 0x10, 0x43, 0xf8, 0x9a, 0x98, 0xe5, 0x53, 0x56, 0xfa, 0xe5, 0x07, | |
0x96, 0x02, 0x84, 0xcf, 0xc8, 0x3f, 0x63, 0xac, 0x55, 0xee, 0x6d, 0x24, 0xb5, 0x5b, 0xff, | |
0x08, 0xb7, | |
]); | |
let mut group = c.benchmark_group("bgra×4_to_rgb×4 (by move)"); | |
// NB: macro for monomorphization | |
macro_rules! bench { | |
($name:expr, $f:ident) => { | |
group.bench_function($name, |b| { | |
let mut rand = rand.clone(); | |
b.iter_batched(|| rand.gen(), |bgra| $f(bgra), BatchSize::SmallInput); | |
}); | |
}; | |
} | |
bench!("loop", convert_loop); | |
bench!("chunks", convert_chunks); | |
bench!("raw", convert_raw); | |
bench!("scatter", convert_scatter); | |
bench!("swizzle", convert_swizzle); | |
bench!("shift", convert_shift); | |
bench!("overwrite", convert_overwrite); | |
} | |
pub fn benchmark_ref(c: &mut Criterion) { | |
// random bytes from random.org | |
let rand = ChaChaRng::from_seed([ | |
0x1c, 0xd7, 0x75, 0x38, 0x10, 0x43, 0xf8, 0x9a, 0x98, 0xe5, 0x53, 0x56, 0xfa, 0xe5, 0x07, | |
0x96, 0x02, 0x84, 0xcf, 0xc8, 0x3f, 0x63, 0xac, 0x55, 0xee, 0x6d, 0x24, 0xb5, 0x5b, 0xff, | |
0x08, 0xb7, | |
]); | |
let mut group = c.benchmark_group("bgra×4_to_rgb×4 (by ref)"); | |
// NB: macro for monomorphization | |
macro_rules! bench { | |
($name:expr, $f:ident) => { | |
group.bench_function($name, |b| { | |
let mut rand = rand.clone(); | |
b.iter_batched_ref(|| rand.gen(), |bgra| $f(bgra), BatchSize::SmallInput); | |
}); | |
}; | |
} | |
bench!("loop", convert_loop_r); | |
bench!("chunks", convert_chunks_r); | |
bench!("raw", convert_raw_r); | |
bench!("scatter", convert_scatter_r); | |
bench!("swizzle", convert_swizzle_r); | |
bench!("shift", convert_shift_r); | |
bench!("overwrite", convert_overwrite_r); | |
} | |
criterion_group!( | |
name = benches; | |
config = Criterion::default(); | |
targets = benchmark_move, benchmark_ref | |
); | |
criterion_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(portable_simd, slice_as_chunks)] | |
// https://users.rust-lang.org/t/converting-a-bgra-u8-to-rgb-u8-n-for-images/67938/7?u=cad97 | |
pub fn convert_loop(bgra: [u8; 16]) -> [u8; 12] { | |
let mut rgb = [0u8; 12]; | |
for i in (0..12).step_by(3) { | |
rgb[i] = bgra[i / 3 * 4 + 2]; | |
rgb[i + 1] = bgra[i / 3 * 4 + 1]; | |
rgb[i + 2] = bgra[i / 3 * 4]; | |
} | |
rgb | |
} | |
pub fn convert_loop_r(bgra: &[u8; 16]) -> [u8; 12] { | |
let mut rgb = [0u8; 12]; | |
for i in (0..12).step_by(3) { | |
rgb[i] = bgra[i / 3 * 4 + 2]; | |
rgb[i + 1] = bgra[i / 3 * 4 + 1]; | |
rgb[i + 2] = bgra[i / 3 * 4]; | |
} | |
rgb | |
} | |
// https://users.rust-lang.org/t/converting-a-bgra-u8-to-rgb-u8-n-for-images/67938/9?u=cad97 | |
pub fn convert_chunks(bgra: [u8; 16]) -> [u8; 12] { | |
let mut rgb: [u8; 12] = [0; 12]; | |
for (src, dst) in bgra.chunks_exact(4).zip(rgb.chunks_exact_mut(3)) { | |
dst[0] = src[2]; | |
dst[1] = src[1]; | |
dst[2] = src[0]; | |
} | |
rgb | |
} | |
pub fn convert_chunks_r(bgra: &[u8; 16]) -> [u8; 12] { | |
let mut rgb: [u8; 12] = [0; 12]; | |
for (src, dst) in bgra.chunks_exact(4).zip(rgb.chunks_exact_mut(3)) { | |
dst[0] = src[2]; | |
dst[1] = src[1]; | |
dst[2] = src[0]; | |
} | |
rgb | |
} | |
// https://users.rust-lang.org/t/converting-a-bgra-u8-to-rgb-u8-n-for-images/67938/12?u=cad97 | |
#[rustfmt::skip] | |
pub fn convert_raw(bgra: [u8; 16]) -> [u8; 12] { | |
let [ | |
b0, g0, r0, _a0, | |
b1, g1, r1, _a1, | |
b2, g2, r2, _a2, | |
b3, g3, r3, _a3, | |
] = bgra; | |
[ | |
r0, g0, b0, | |
r1, g1, b1, | |
r2, g2, b2, | |
r3, g3, b3, | |
] | |
} | |
#[rustfmt::skip] | |
pub fn convert_raw_r(bgra: &[u8; 16]) -> [u8; 12] { | |
let [ | |
b0, g0, r0, _a0, | |
b1, g1, r1, _a1, | |
b2, g2, r2, _a2, | |
b3, g3, r3, _a3, | |
] = *bgra; | |
[ | |
r0, g0, b0, | |
r1, g1, b1, | |
r2, g2, b2, | |
r3, g3, b3, | |
] | |
} | |
pub fn convert_scatter(bgra: [u8; 16]) -> [u8; 12] { | |
use std::simd::Simd; //u8x16; | |
let vector = Simd::from_array(bgra); | |
let mut rgb = [0; 12]; | |
#[rustfmt::skip] | |
let idxs = [ | |
2, 1, 0, !0, | |
5, 4, 3, !0, | |
8, 7, 6, !0, | |
11, 10, 9, !0, | |
]; | |
vector.scatter(&mut rgb, Simd::from_array(idxs)); | |
rgb | |
} | |
pub fn convert_scatter_r(bgra: &[u8; 16]) -> [u8; 12] { | |
use std::simd::Simd; //u8x16; | |
let vector = Simd::from_array(*bgra); | |
let mut rgb = [0; 12]; | |
#[rustfmt::skip] | |
let idxs = [ | |
2, 1, 0, !0, | |
5, 4, 3, !0, | |
8, 7, 6, !0, | |
11, 10, 9, !0, | |
]; | |
vector.scatter(&mut rgb, Simd::from_array(idxs)); | |
rgb | |
} | |
pub fn convert_swizzle(bgra: [u8; 16]) -> [u8; 12] { | |
use std::simd::{simd_swizzle, Simd}; | |
let bgra = Simd::from_array(bgra); | |
#[rustfmt::skip] | |
const IDXS: [usize; 16] = [ | |
2, 1, 0, | |
6, 5, 4, | |
10, 9, 8, | |
14, 13, 12, | |
3, 7, 11, 15, | |
]; | |
let rgb = simd_swizzle!(bgra, IDXS); | |
rgb.to_array().as_chunks().0[0] | |
} | |
pub fn convert_swizzle_r(bgra: &[u8; 16]) -> [u8; 12] { | |
use std::simd::{simd_swizzle, Simd}; | |
let bgra = Simd::from_array(*bgra); | |
#[rustfmt::skip] | |
const IDXS: [usize; 16] = [ | |
2, 1, 0, | |
6, 5, 4, | |
10, 9, 8, | |
14, 13, 12, | |
3, 7, 11, 15, | |
]; | |
let rgb = simd_swizzle!(bgra, IDXS); | |
rgb.to_array().as_chunks().0[0] | |
} | |
pub fn convert_shift(bgra: [u8; 16]) -> [u8; 12] { | |
let bgra = bgra.as_chunks().0; | |
let mut buffer = 0_u128; | |
for bgra in bgra.iter().cloned().rev() { | |
buffer <<= 24; | |
buffer |= u128::from(u32::from_be_bytes(bgra) >> 8); | |
} | |
buffer.to_le_bytes().as_chunks().0[0] | |
} | |
pub fn convert_shift_r(bgra: &[u8; 16]) -> [u8; 12] { | |
let bgra = bgra.as_chunks().0; | |
let mut buffer = 0_u128; | |
for bgra in bgra.iter().cloned().rev() { | |
buffer <<= 24; | |
buffer |= u128::from(u32::from_be_bytes(bgra) >> 8); | |
} | |
buffer.to_le_bytes().as_chunks().0[0] | |
} | |
pub fn convert_overwrite(bgra: [u8; 16]) -> [u8; 12] { | |
let bgra = bgra.as_chunks().0; | |
let mut padded_rgb = [0; 13]; | |
for i in (0..4).rev() { | |
let pixel = u32::from_be_bytes(bgra[i]); | |
padded_rgb[i * 3..][..4].copy_from_slice(&pixel.to_le_bytes()); | |
} | |
padded_rgb[1..].as_chunks().0[0] | |
} | |
pub fn convert_overwrite_r(bgra: &[u8; 16]) -> [u8; 12] { | |
let bgra = bgra.as_chunks().0; | |
let mut padded_rgb = [0; 13]; | |
for i in (0..4).rev() { | |
let pixel = u32::from_be_bytes(bgra[i]); | |
padded_rgb[i * 3..][..4].copy_from_slice(&pixel.to_le_bytes()); | |
} | |
padded_rgb[1..].as_chunks().0[0] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment