Skip to content

Instantly share code, notes, and snippets.

@CAD97

CAD97/benches.rs Secret

Created Nov 28, 2021
Embed
What would you like to do?
bgra_to_rgb benchmark
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);
#![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