I changed the enum
method to trait
method, then the speed is slower again:
use std::{iter::{Map, Zip}, slice::Iter, ops::{Add, Sub, Mul, Div}};
pub struct MyVec(pub Vec<f32>);
pub struct MyAdd;
pub trait Ops<T, N> {
type Output;
fn ops_on(&self, data: (T, N)) -> Self::Output;
}
impl<T, N, K> Ops<T, N> for MyAdd
where
T: Add<N, Output = K>,
{
type Output = K;
fn ops_on(&self, data: (T, N)) -> Self::Output {
data.0 + data.1
}
}
#[derive(Clone)]
pub struct MyMap<I, F> {
pub(crate) iter: I,
f: F,
}
impl<I, F> MyMap<I, F> {
fn vec(self) -> MyVec
where
Self: Iterator<Item = f32>,
{
MyVec(self.collect::<Vec<f32>>())
}
}
impl<I, F, T, N> Iterator for MyMap<I, F>
where
I: Iterator<Item = (T, N)>,
F: Ops<T, N>,
{
type Item = <F as Ops<T, N>>::Output;
fn next(&mut self) -> Option<Self::Item> {
if let Some(data) = self.iter.next() {
Some(self.f.ops_on(data))
} else {
None
}
}
}
impl<'a> Add<&'a MyVec> for &'a MyVec {
type Output = MyMap<Zip<Iter<'a, f32>, Iter<'a, f32>>, MyAdd>;
fn add(self, rhs: &'a MyVec) -> Self::Output {
let iter = self.0.iter().zip(rhs.0.iter());
MyMap { iter, f: MyAdd }
}
}
impl<'a, I, F> Add<&'a MyVec> for MyMap<I, F>
where
Self: Iterator<Item = f32>,
{
type Output = MyMap<Zip<Self, Iter<'a, f32>>, MyAdd>;
fn add(self, rhs: &'a MyVec) -> Self::Output {
MyMap {
iter: self.zip(rhs.0.iter()),
f: MyAdd,
}
}
}
impl<'a, I, F> Add<MyMap<I, F>> for &'a MyVec
where
MyMap<I, F>: Iterator<Item = f32>,
{
type Output = MyMap<Zip<MyMap<I, F>, Iter<'a, f32>>, MyAdd>;
fn add(self, rhs: MyMap<I, F>) -> Self::Output {
MyMap {
iter: rhs.zip(self.0.iter()),
f: MyAdd,
}
}
}
fn main() {
let v = vec![1f32; 100_000_000];
let my_vec = MyVec(v.clone());
let time_start = std::time::Instant::now();
let k1 = v.iter().zip(v.iter()).map(|(x, y)| x + y);
let k2 = k1.zip(v.iter()).map(|(x, y)| x + y);
let k3 = v.iter().zip(k2).map(|(x, y)| x + y);
let res = k3.collect::<Vec<f32>>();
println!("{:?} {:?}", &res[..10], time_start.elapsed());
let time_start = std::time::Instant::now();
let k1 = &my_vec + &my_vec;
let k2 = k1 + &my_vec;
let k3 = &my_vec + k2;
let res = k3.vec();
println!("{:?} {:?}", &res.0[..10], time_start.elapsed());
}
This is the playground.
I thought the reason maybe that Iterator
implementing on MyMap
by myself is slower than Iterator
implementing on Vec<f32>
.