如果我知道某个参数的定义域可能在几个选择值中,是否可以要求编译器优化代码?
例如
// x will be within 1..10
fn foo(x: u32, y: u32) -> u32 {
// some logic
}
上述函数应编译为
fn foo(x: u32, y: u32) -> u32 {
match x {
1 => foo1(y), // foo1 is generated by the compiler from foo, optimized for when x == 1
2 => foo2(y), // foo2 is generated by the compiler from foo, optimized for when x == 2
...
10 => foo10(y),
_ => foo_default(x, y) // unoptimized foo logic
}
}
我希望编译器根据一些提示生成上面的重写。
2条答案
按热度按时间k5ifujac1#
您可以将逻辑放入
#[inline(always)]
foo_impl()
中,然后使用所需的值调用它:因为
#[inline(always)]
,编译器会内联所有的foo_impl()
调用,然后使用常量来优化调用。没有什么是保证的,但它应该是相当可靠的(虽然还没有测试)。确保基准:这实际上可能是由于代码膨胀而导致的回归。
m2xkgtsf2#
让我们以这个玩具为例:
但是在你的应用程序中,你知道
x
很可能每次都是2
,我们可以用std::intrinsics::likely
把它传递给编译器:一个二个一个一个
免责声明:我没有足够的经验来知道这是一个 * 好 * 优化与否,只是提示改变了输出。
不幸的是,虽然我认为这是最清晰的语法,但
std::intrinsics
并不稳定。幸运的是,我们可以使用#[cold]
属性获得相同的行为,该属性在stable上可用,可以将您的愿望传达给编译器:我很怀疑把这个应用到你的用例中是否真的会产生你所提出的转换,我认为这对常量传播有很大的影响,甚至编译器愿意把
x < 10
优化成一个10个常量的分支,但是使用上面的提示会让它决定什么是最好的。但是有时候,您知道什么比编译器更好,并且可以通过手动应用转换来强制常量传播:就像你在最初的例子中所做的那样,或者在"ChayimFriedman"的回答中用不同的方式。