Rust是否允许优化器更改程序的结果?

问题描述 投票:0回答:1

[在某些语言中,允许通过优化来更改程序执行结果。例如,

  • C ++ 11具有“ copy-elision”的概念,该概念使优化程序在某些情况下可以忽略副本构造函数(及其副作用)。

  • Swift具有“不精确的生存期”的概念,它使优化程序可以在词法作用域结束之前的最后一次使用之后的任何时间释放对象。

在两种情况下,都不能保证会发生优化,因此,基于优化器的实现(例如,调试与发布版本),程序的执行结果可能会显着不同。

可以跳过复制,在引用处于活动状态时对象可能会死亡。解决这些问题的唯一方法是防御,使程序正确运行,而不管优化是否发生。如果您不知道此行为的存在,则无法使用工具编写正确的程序。

这不同于程序员编写的有意产生随机结果的“随机操作”。这些行为是(1)由优化程序完成的,并且(2)可以使执行结果随机化,而不考虑程序员的意图。这是由语言设计人员为获得更好性能而设计的。在性能和可预测性之间进行权衡。

Rust是否有(或考虑过)任何这种行为?允许更改程序执行结果以提高性能的任何优化。如果有,它的行为是什么,为什么允许这样做?

我知道“执行结果”一词可能含糊不清,但我不知道这是一个合适的术语。对此我感到抱歉。

我想在这里收集所有可能的案例,这样每个人都可以意识到它们并为它们做好准备。如果您认为您的案件产生了不同的结果,请张贴任何案件作为答案(或评论)。

rust compiler-optimization
1个回答
-1
投票

与C ++相比,Rust中的脚步枪要少得多。通常,它们围绕unsafe,从其派生的原始指针和生存期或任何形式的未定义行为(实际上在Rust中也未定义)围绕。但是,如果您的代码编译(并且如果有疑问,则通过cargo miri test),则您很可能不会看到令人惊讶的行为。

想到的两个例子可能令人惊讶:

[MutexGuard的生命周期;该示例来自the book

while let Ok(job) = receiver.lock().unwrap().recv() {
    job();
}

[一个人可能会认为/希望Mutex上的receiver在获得作业后被释放,job()在其他线程可以接收作业的同时执行。但是,由于位置表达式上下文中的值表达式与临时生存期结合使用的方式(MutexGuard需要引用receiver的匿名生存期),因此MutexGuard保留了整个while-块。这意味着只有一个线程将执行作业。

如果您这样做

loop {
    let job = receiver.lock().unwrap().recv().unwrap();
    job();
}

这将允许多个线程并行运行。原因尚不清楚。

多次遇到有关const的问题。编译器无法保证const实际上仅存在一次(作为优化),还是在使用它的任何地方实例化。第二种情况是人们思考const的方式,但是不能保证这就是编译器所做的。所以这可能发生:

const EXAMPLE: Option<i32> = Some(42);
fn main() {
    assert_eq!(EXAMPLE.take(), Some(42));
    assert_eq!(EXAMPLE, Some(42)); // Where did this come from?
}
© www.soinside.com 2019 - 2024. All rights reserved.