JIT 编译器是否优化(内联)不必要的变量声明?

发布于 2024-12-10 23:40:02 字数 920 浏览 0 评论 0原文

我读过几篇文章和问题/答案,得出的结论是最佳实践是让 JIT 编译器对内联函数调用进行所有优化。有道理。

内联变量声明怎么样?编译器也会优化这些吗?

也就是说,会不会:

        Dim h = (a + b + c) / 2       'Half-Perimeter

        If maxEdgeLength / (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) <= MaximumTriangleAspectRatio Then
           'Do stuff here.
        End If

比这个有更好的性能:

        Dim perimeter = a + b + c   'Perimeter
        Dim h = perimeter / 2       'Half-Perimeter

        Dim area = Math.Sqrt(h * (h - a) * (h - b) * (h - c)) 'Heron's forumula.
        Dim inradius = area / h
        Dim aspectRatio = maxEdgeLength / inradius

        If aspectRatio <= MaximumTriangleAspectRatio Then
            'Do stuff here.
        End If

当然我更喜欢后者,因为它更容易阅读和调试,但如果它存在的话,我无法承受性能下降。

注意:我已经将此代码确定为瓶颈——无需反驳过早优化。 :-)

I've read several articles and questions/answers that conclude the best practice is to let the JIT compiler do all the optimization for inline function calls. Makes sense.

What about inline variable declarations? Does the compiler optimize these as well?

That is, will this:

        Dim h = (a + b + c) / 2       'Half-Perimeter

        If maxEdgeLength / (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) <= MaximumTriangleAspectRatio Then
           'Do stuff here.
        End If

Have better performance than this:

        Dim perimeter = a + b + c   'Perimeter
        Dim h = perimeter / 2       'Half-Perimeter

        Dim area = Math.Sqrt(h * (h - a) * (h - b) * (h - c)) 'Heron's forumula.
        Dim inradius = area / h
        Dim aspectRatio = maxEdgeLength / inradius

        If aspectRatio <= MaximumTriangleAspectRatio Then
            'Do stuff here.
        End If

Of course I prefer the latter because it's easier to read and debug, but I can't afford the performance degradation if it exists.

Note: I have already identified this code as a bottleneck -- No need for retorts about premature optimization. :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

倾其所爱 2024-12-17 23:40:02

临时变量有没有名字都不是问题。

但你可以显着优化这种不平等。

您的代码是:

If maxEdgeLength / (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) <= MaximumTriangleAspectRatio Then

将两边乘以平方根,消除除法(保留不等式,因为平方根不能返回负数):

If maxEdgeLength <= (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) * MaximumTriangleAspectRatio Then

现在,将两边平方以消除昂贵的平方根:

If maxEdgeLength * maxEdgeLength <= h * (h - a) * (h - b) * (h - c) / h / h * MaximumTriangleAspectRatio * MaximumTriangleAspectRatio Then

取消,并乘以 h

If maxEdgeLength * maxEdgeLength * h <= (h - a) * (h - b) * (h - c) * MaximumTriangleAspectRatio * MaximumTriangleAspectRatio Then

这样会快很多。如果重复此计算,请考虑缓存此表达式的部分结果以获得更多改进。

使用注释来解释公式。摆脱瓶颈函数中的 Math.Sqrt 调用值得以不太简单的格式编写表达式。

Temporary variables having names or not is a non-issue.

But you can optimize that inequality significantly.

Your code was:

If maxEdgeLength / (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) <= MaximumTriangleAspectRatio Then

Multiply both sides by the square root, eliminating division (inequality is preserved, because square root cannot return a negative number):

If maxEdgeLength <= (Math.Sqrt(h * (h - a) * (h - b) * (h - c)) / h) * MaximumTriangleAspectRatio Then

Now, square both sides to eliminate that expensive square root:

If maxEdgeLength * maxEdgeLength <= h * (h - a) * (h - b) * (h - c) / h / h * MaximumTriangleAspectRatio * MaximumTriangleAspectRatio Then

Cancel, and multiply by h.

If maxEdgeLength * maxEdgeLength * h <= (h - a) * (h - b) * (h - c) * MaximumTriangleAspectRatio * MaximumTriangleAspectRatio Then

This will be a lot faster. If this calculation is repeated, consider caching the results of part of this expression for even more improvement.

Use comments to explain the formula. Getting rid of a Math.Sqrt call in a bottleneck function is worth writing the expression in a less-than-simple format.

心是晴朗的。 2024-12-17 23:40:02

顺便说一句,只是为了唱反调,我也想指出这一点:

整个函数的 JIT 内联着眼于 MSIL 的长度(以字节为单位),而不是计算的复杂性。添加局部变量(并期望 JIT 注册它们)可能会增加函数的 MSIL 大小,足以使整个函数不适合内联。

这不太可能像不必要地使用 Math.Sqrt 那样产生那么大的影响,但这是有可能的。正如埃里克·利珀特(Eric Lippert)所说,通过实际测量你会了解更多。然而,这种测量仅对程序的一次特定运行有效,并且不能推广到经常调整 JIT 行为的不同处理器或 .NET 运行时的未来版本(包括服务包)。因此,您需要一种结合分析和经验的优化方法。

By the way, just to play devil's advocate, also I wanted to point this out:

JIT inlining of the entire function looks at the length, in bytes of MSIL, and not the complexity of the calculation. Adding local variables (and expecting the JIT to enregister them) might increase the MSIL size of the function enough to make the whole function not a candidate for inlining.

This isn't likely to make as big a difference as unnecessary use of Math.Sqrt, but it is a possibility. As Eric Lippert said, you'll know more by actually measuring. However, such a measurement is only valid for one particular run of the program, and does not generalize to different processors or future versions of the .NET runtime (including service packs) that often tweak JIT behavior. So you want a combined analytical and empirical approach to optimization.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文