.NET JIT 是否会内联一个调用另一个小函数的小函数?
我想知道 - .NET JITter 是否会递归内联从其他小函数调用的小函数?
举个例子:
public static float Square(float value)
{
return value * value;
}
public static float Cube(float value)
{
return Square(value) * value;
}
如果我从某个地方调用 Cube ,它会一直内联,还是最终会调用 Square 的函数?
如果是这样,它会递归多深来进行内联? (假设我疯狂地以同样的方式实现了 Quartic 或 Quintic 函数。)
I would like to know - will the .NET JITter recursively inline small functions called from other small functions?
Just for example:
public static float Square(float value)
{
return value * value;
}
public static float Cube(float value)
{
return Square(value) * value;
}
If I call Cube
from somewhere, will it inline all the way, or will I end up with a function call to Square
?
And, if so, how deep will it recurse to do the inlining? (Say I were crazy enough to implement a Quartic
or Quintic
function in the same way.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不幸的是你选了一个不好的例子。 x86 JIT 编译器不内联返回浮点型的方法。不是 100% 确定原因,我认为它确实可以避免在 FPU 中将浮点数转换为 80 位浮点值时出现一致的问题。内部精度为 80 位,但当 80 位值刷新回内存时被截断回 32 位值时,这些额外的位将被切掉。将值保留在 FPU 中的时间过长可以防止发生这种截断并更改计算结果。
如果将 float 替换为 double 并编译此代码:
那么启用 JIT 优化器时会生成此机器代码:
它不仅内联函数,还能够在编译时计算表达式。并通过调用Console.WriteLine(8.0)直接传递结果。相当不错吧?
使用双精度,而不是浮动。
Unfortunately you picked a bad example. The x86 JIT compiler doesn't inline methods that return float. Not 100% sure why, I think it does to avoid consistently problems when the float is converted to an 80-bit floating point value in the FPU. Internal precision is 80-bits but those extra bits are sliced off when the 80-bit value is truncated back to a 32-bit value when it is flushed back to memory. Keeping the value in the FPU too long prevents this truncation from happening and changes the calculation result.
If you replace float by double and compile this code:
Then this machine code is generated when the JIT optimizer is enabled:
Not only did it inline the functions, it was able to evaluate the expressions at compile time. And directly passes the result by calling Console.WriteLine(8.0). Pretty good huh?
Use double, not float.