use criterion::{black_box, criterion_group, criterion_main, Bencher, BenchmarkId, Criterion}; use half::prelude::*; use std::{f32, f64, iter}; const SIMD_LARGE_BENCH_SLICE_LEN: usize = 1024; fn bench_f32_to_f16(c: &mut Criterion) { let mut group = c.benchmark_group("Convert f16 From f32"); for val in &[ 0., -0., 1., f32::MIN, f32::MAX, f32::MIN_POSITIVE, f32::NEG_INFINITY, f32::INFINITY, f32::NAN, f32::consts::E, f32::consts::PI, ] { group.bench_with_input(BenchmarkId::new("f16::from_f32", val), val, |b, i| { b.iter(|| f16::from_f32(*i)) }); } } fn bench_f64_to_f16(c: &mut Criterion) { let mut group = c.benchmark_group("Convert f16 From f64"); for val in &[ 0., -0., 1., f64::MIN, f64::MAX, f64::MIN_POSITIVE, f64::NEG_INFINITY, f64::INFINITY, f64::NAN, f64::consts::E, f64::consts::PI, ] { group.bench_with_input(BenchmarkId::new("f16::from_f64", val), val, |b, i| { b.iter(|| f16::from_f64(*i)) }); } } fn bench_f16_to_f32(c: &mut Criterion) { let mut group = c.benchmark_group("Convert f16 to f32"); for val in &[ f16::ZERO, f16::NEG_ZERO, f16::ONE, f16::MIN, f16::MAX, f16::MIN_POSITIVE, f16::NEG_INFINITY, f16::INFINITY, f16::NAN, f16::E, f16::PI, ] { group.bench_with_input(BenchmarkId::new("f16::to_f32", val), val, |b, i| { b.iter(|| i.to_f32()) }); } } fn bench_f16_to_f64(c: &mut Criterion) { let mut group = c.benchmark_group("Convert f16 to f64"); for val in &[ f16::ZERO, f16::NEG_ZERO, f16::ONE, f16::MIN, f16::MAX, f16::MIN_POSITIVE, f16::NEG_INFINITY, f16::INFINITY, f16::NAN, f16::E, f16::PI, ] { group.bench_with_input(BenchmarkId::new("f16::to_f64", val), val, |b, i| { b.iter(|| i.to_f64()) }); } } criterion_group!( f16_sisd, bench_f32_to_f16, bench_f64_to_f16, bench_f16_to_f32, bench_f16_to_f64 ); fn bench_slice_f32_to_f16(c: &mut Criterion) { let mut constant_buffer = [f16::ZERO; 11]; let constants = [ 0., -0., 1., f32::MIN, f32::MAX, f32::MIN_POSITIVE, f32::NEG_INFINITY, f32::INFINITY, f32::NAN, f32::consts::E, f32::consts::PI, ]; c.bench_function( "HalfFloatSliceExt::convert_from_f32_slice/constants", |b: &mut Bencher<'_>| { b.iter(|| black_box(&mut constant_buffer).convert_from_f32_slice(black_box(&constants))) }, ); let large: Vec<_> = iter::repeat(0) .enumerate() .map(|(i, _)| i as f32) .take(SIMD_LARGE_BENCH_SLICE_LEN) .collect(); let mut large_buffer = [f16::ZERO; SIMD_LARGE_BENCH_SLICE_LEN]; c.bench_function( "HalfFloatSliceExt::convert_from_f32_slice/large", |b: &mut Bencher<'_>| { b.iter(|| black_box(&mut large_buffer).convert_from_f32_slice(black_box(&large))) }, ); } fn bench_slice_f64_to_f16(c: &mut Criterion) { let mut constant_buffer = [f16::ZERO; 11]; let constants = [ 0., -0., 1., f64::MIN, f64::MAX, f64::MIN_POSITIVE, f64::NEG_INFINITY, f64::INFINITY, f64::NAN, f64::consts::E, f64::consts::PI, ]; c.bench_function( "HalfFloatSliceExt::convert_from_f64_slice/constants", |b: &mut Bencher<'_>| { b.iter(|| black_box(&mut constant_buffer).convert_from_f64_slice(black_box(&constants))) }, ); let large: Vec<_> = iter::repeat(0) .enumerate() .map(|(i, _)| i as f64) .take(SIMD_LARGE_BENCH_SLICE_LEN) .collect(); let mut large_buffer = [f16::ZERO; SIMD_LARGE_BENCH_SLICE_LEN]; c.bench_function( "HalfFloatSliceExt::convert_from_f64_slice/large", |b: &mut Bencher<'_>| { b.iter(|| black_box(&mut large_buffer).convert_from_f64_slice(black_box(&large))) }, ); } fn bench_slice_f16_to_f32(c: &mut Criterion) { let mut constant_buffer = [0f32; 11]; let constants = [ f16::ZERO, f16::NEG_ZERO, f16::ONE, f16::MIN, f16::MAX, f16::MIN_POSITIVE, f16::NEG_INFINITY, f16::INFINITY, f16::NAN, f16::E, f16::PI, ]; c.bench_function( "HalfFloatSliceExt::convert_to_f32_slice/constants", |b: &mut Bencher<'_>| { b.iter(|| black_box(&constants).convert_to_f32_slice(black_box(&mut constant_buffer))) }, ); let large: Vec<_> = iter::repeat(0) .enumerate() .map(|(i, _)| f16::from_f32(i as f32)) .take(SIMD_LARGE_BENCH_SLICE_LEN) .collect(); let mut large_buffer = [0f32; SIMD_LARGE_BENCH_SLICE_LEN]; c.bench_function( "HalfFloatSliceExt::convert_to_f32_slice/large", |b: &mut Bencher<'_>| { b.iter(|| black_box(&large).convert_to_f32_slice(black_box(&mut large_buffer))) }, ); } fn bench_slice_f16_to_f64(c: &mut Criterion) { let mut constant_buffer = [0f64; 11]; let constants = [ f16::ZERO, f16::NEG_ZERO, f16::ONE, f16::MIN, f16::MAX, f16::MIN_POSITIVE, f16::NEG_INFINITY, f16::INFINITY, f16::NAN, f16::E, f16::PI, ]; c.bench_function( "HalfFloatSliceExt::convert_to_f64_slice/constants", |b: &mut Bencher<'_>| { b.iter(|| black_box(&constants).convert_to_f64_slice(black_box(&mut constant_buffer))) }, ); let large: Vec<_> = iter::repeat(0) .enumerate() .map(|(i, _)| f16::from_f64(i as f64)) .take(SIMD_LARGE_BENCH_SLICE_LEN) .collect(); let mut large_buffer = [0f64; SIMD_LARGE_BENCH_SLICE_LEN]; c.bench_function( "HalfFloatSliceExt::convert_to_f64_slice/large", |b: &mut Bencher<'_>| { b.iter(|| black_box(&large).convert_to_f64_slice(black_box(&mut large_buffer))) }, ); } criterion_group!( f16_simd, bench_slice_f32_to_f16, bench_slice_f64_to_f16, bench_slice_f16_to_f32, bench_slice_f16_to_f64 ); fn bench_f32_to_bf16(c: &mut Criterion) { let mut group = c.benchmark_group("Convert bf16 From f32"); for val in &[ 0., -0., 1., f32::MIN, f32::MAX, f32::MIN_POSITIVE, f32::NEG_INFINITY, f32::INFINITY, f32::NAN, f32::consts::E, f32::consts::PI, ] { group.bench_with_input(BenchmarkId::new("bf16::from_f32", val), val, |b, i| { b.iter(|| bf16::from_f32(*i)) }); } } fn bench_f64_to_bf16(c: &mut Criterion) { let mut group = c.benchmark_group("Convert bf16 From f64"); for val in &[ 0., -0., 1., f64::MIN, f64::MAX, f64::MIN_POSITIVE, f64::NEG_INFINITY, f64::INFINITY, f64::NAN, f64::consts::E, f64::consts::PI, ] { group.bench_with_input(BenchmarkId::new("bf16::from_f64", val), val, |b, i| { b.iter(|| bf16::from_f64(*i)) }); } } fn bench_bf16_to_f32(c: &mut Criterion) { let mut group = c.benchmark_group("Convert bf16 to f32"); for val in &[ bf16::ZERO, bf16::NEG_ZERO, bf16::ONE, bf16::MIN, bf16::MAX, bf16::MIN_POSITIVE, bf16::NEG_INFINITY, bf16::INFINITY, bf16::NAN, bf16::E, bf16::PI, ] { group.bench_with_input(BenchmarkId::new("bf16::to_f32", val), val, |b, i| { b.iter(|| i.to_f32()) }); } } fn bench_bf16_to_f64(c: &mut Criterion) { let mut group = c.benchmark_group("Convert bf16 to f64"); for val in &[ bf16::ZERO, bf16::NEG_ZERO, bf16::ONE, bf16::MIN, bf16::MAX, bf16::MIN_POSITIVE, bf16::NEG_INFINITY, bf16::INFINITY, bf16::NAN, bf16::E, bf16::PI, ] { group.bench_with_input(BenchmarkId::new("bf16::to_f64", val), val, |b, i| { b.iter(|| i.to_f64()) }); } } criterion_group!( bf16_sisd, bench_f32_to_bf16, bench_f64_to_bf16, bench_bf16_to_f32, bench_bf16_to_f64 ); criterion_main!(f16_sisd, bf16_sisd, f16_simd);