获取数组切片和获取数组引用作为参数有什么区别?

3
什么是获取切片的区别:
fn relu(xs: &mut [f64]) {
    xs.iter_mut().for_each(|x| *x = x.max(0.0));
}

引用数组

fn relu<const L: usize>(xs: &mut [f64; L]) {
    xs.iter_mut().for_each(|x| *x = x.max(0.0));
}

作为参数?

这两者都有它们的用途,还是其中一个严格地比另一个更好?

1个回答

4

嗯,一个切片更加通用,因为它可以使用更多类型:

fn relu(xs: &mut [f64]) {
    xs.iter_mut().for_each(|x| *x = x.max(0.0));
}

你可以在&mut Vec&mut []&mut [_; N](几乎任何可以制作切片的类型,记住切片只是某些连续序列的视图)上调用relu,因为这些类型可以用作切片。
同时:
fn relu<const L: usize>(xs: &mut [f64; L]) {
    xs.iter_mut().for_each(|x| *x = x.max(0.0));
}

只能在[f64; L]中使用,并且每个使用的L都会生成一个新函数,这在这种情况下几乎是资源的浪费

如@Masklinn所述:

另一方面,对数组的引用意味着迭代大小在编译时肯定已知,这可以允许优化,而切片版本可能无法计算出。因此,有时使用数组引用作为优化辅助可能是有意义的(在这种情况下,relu可能是主要的内联候选对象,所以重要的部分实际上是调用者中的类型)。


2
另一方面,数组的引用意味着迭代大小在编译时肯定已知,这可以允许优化,而切片版本可能无法解决。因此,有时使用数组引用作为优化辅助可能是有意义的(在这种情况下,“relu”可能是内联的主要候选对象,因此真正重要的部分实际上是调用者中的类型)。 - Masklinn
@Masklinn,确实,好观点,谢谢!我可以将其作为答案的一部分添加吗,还是您想自己添加? - Netwave
好的,请继续,这只是一个侧记,以便读者不会认为对数组的引用总是错误(与共享向量或字符串的引用不同)。 - Masklinn
数组引用的另一个缺点是它们是单态化的,导致代码膨胀。即使优化器可能会去重,但仍需要额外的时间。 - Chayim Friedman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接