编译器会收到一个指向某段内存的指针 。由于该内存包含了一个复杂的结构(即:ptr、len、capacity triple),因此它很难推理出该结构的演变 。对此,编译器可以从内存中加载该结构,并使用一堆标量局部变量,来进行替换聚合:
fn permute(xs: &mut Vec<i32>) {local ptr: ptrlocal len: usizelocal cap: usizeload ptr xs.ptrload len xs.lenload cap xs.cap...store xs.ptr ptrstore xs.len lenstore xs.cap cap}如此,编译器再次获得了推理能力 。虽然与内联类似,但是SROA主要用于内存,而不是代码 。
3、不可能与可能使用编译器模型的主要优势在于:
- 在每个函数的基础上进行优化
- 可以进行内联函数的调用
- 擅长发现局部变量之间的关系,并据此重新排列代码
- 能够对内存进行有限的推理(即,决定何时适合load或store) 。
这也就是为什么在Rust中,每个函数都有一个唯一的、大小为零(zero-sized)的类型,而且并没有运行时(runtime)的表示 。它静态的方式保证了编译器始终可以内联到代码上,以使得抽象的成本为零,毕竟任何优化编译器都会将其“融化”为零 。
当然,更高级别的语言则可能会选择始终使用函数指针去表示函数 。实际上,在许多情况下,它们生成的代码就等效为可优化的 。不过,在源代码中是不会有任何迹象来表明这是一个可优化的情况(实际指针在编译时是可知的),还是真正的动态调用状况 。因此,使用Rust就保证了可优化和潜在可优化之间的区别,能够反映在源语言之中,请参见如下代码段:
// Compiler is guaranteed to be able to inline call to `f`.fn call1<F: Fn()>(f: F) {f()}// Compiler _might_ be able to inline call to `f`.fn call2(f: fn()) {f()}由上述代码可知,其第一条规则便是使大多数调用可以被静态解析,以允许内联 。而函数指针和动态调度则会防止内联 。此外,内存中的间接寻址也会给编译器带来如下麻烦:struct Foo {bar: Bar,baz: Baz,}显然,上述Foo结构对编译器是完全透明的 。不过,让我们稍作如下修改:struct Foo {bar: Box<Bar>,baz: Baz,}上述结果就不那么明确了 。也就是说,被Foo占用的内存一般不会转移到被Bar占用的内存处 。同样,在许多情况下,鉴于唯一性,编译器可以通过box进行“不保证”的推理 。如下代码段展示了map是如何被签名和定义的 。
#[inline]fn map<B, F>(self, f: F) -> Map<Self, F>whereSelf: Sized,F: FnMut(Self::Item) -> B,{Map::new(self, f)}关于内存的另一个重点是,一般而言,编译器不能改变整体布局 。SROA可以将一些数据结构加载到一堆局部变量中,然后可以用“一对指针”代替“一个指针和一个索引”的表示 。不过,SROA最终将不得不具体化“一个指针和一个索引”,并将该表示存储回内存之中 。这是因为内存布局是在所有函数之间共享的,因此函数不能单方面地指定更优化的表示 。总之,只要能够“看到”代码,编译器就能够更擅长推理代码 。因此,请确保大多数调用在编译时可以实现内联 。
四、SIMD让我们将前面讨论的、为编译器提供可优化代码的通用框架,应用到自动矢量化上 。下面是我们优化计算两个字节片之间最长公共前缀的函数 。
use std::iter::zip;// 650 millisecondsfn common_prefix(xs: &[u8], ys: &[u8]) -> usize {let mut result = 0;for (x, y) in zip(xs, ys) {if x != y { break; }result += 1}result}如果您已经有了自动矢量化的模型,或者已查看了汇编的输出,那么就会发现一次仅处理一个字节的函数,效率非常慢 。我们该如何解决这个问题呢?SIMD既然可以同时处理多个值,那么我们就希望编译器能够同时比较一堆字节 。例如,我们通过如下代码段,先一次性处理16个字节,然后分别处理剩余部分,以便使得结构更加显式化:
推荐阅读
- 图解DHCP协议,搞懂你的电脑/手机如何自动获取IP的
- 我们一起聊聊MySQL中的游标,你学会了吗?
- 车辆免检后,接下来需要做什么?手把手教你→
- 书房这样设计,让你的生活更有品质
- 养一台比亚迪海豹一年需要多少钱?算出来你还会考虑燃油车吗?
- 被行政拘留过还可以开无犯罪证明吗?
- 快充、闪充、无线充?一字之差相差千里!别让你的手机提前报废
- 微信wxid被泄露:如何保护自己的账号安全?
- 你的抖音还有一直没流量吗?干货教你玩转抖音精髓!
- 抖音feed流广告与信息流广告区别有哪些?
