过度使用函数调用会影响性能吗?特别是在 Fortran 语言中

发布于 2024-09-09 04:23:26 字数 256 浏览 5 评论 0原文

我习惯性地编写带有很多函数的代码,我发现这样更清晰。但现在我正在用 Fortran 编写一些需要非常高效的代码,我想知道过度使用函数是否会减慢速度,或者编译器是否会找出正在发生的事情并进行优化?

我知道在 Java/Python 等中每个函数都是一个对象,因此创建大量函数需要在内存中创建它们。我还知道,在 Haskell 中,函数是相互简化的,所以它们之间没有什么区别。

有人知道 Fortran 的情况吗?使用意图/纯函数/声明更少的局部变量/其他有什么区别吗?

I habitually write code with lots of functions, I find it makes it clearer. But now I'm writing some code in Fortran which needs to be very efficient, and I'm wondering whether over-using functions will slow it down, or whether the compiler will work out what's going on and optimise?

I know in Java/Python etc each function is an object, and so creating lots of functions would require them to be created in memory. I also know that in Haskell the functions are reduced into each other, so it makes little difference there.

Does anyone know about the case with Fortran? Is there a difference with using intent/pure functions/declaring fewer local variables/anything else?

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

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

发布评论

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

评论(4

遗忘曾经 2024-09-16 04:23:27

对于基于堆栈的语言(例如 Fortran),函数调用会带来性能成本。他们必须添加到堆栈等。

因此,如果可能的话,大多数编译器都会尝试积极地内联函数调用。大多数时候,编译器会就是否在程序中内联某些函数做出正确的选择。

这种自动内联过程意味着编写函数(根本)不需要额外的成本。

这意味着您应该尽可能干净且有组织地编写代码,并且编译器很可能会为您进行这些优化。更重要的是,解决问题的整体策略是最有效的,而不是担心函数调用的性能。

Function calls carry a performance cost for stack based languages, like Fortran. They have to add on to the stack and such.

Because of this, most compilers will try to inline function calls aggressively, if it is possible. Most of the time the compiler will make the right choice on whether or not to inline certain functions in your program.

This automatic inlining process will mean that there is no extra cost for writing your function (at all).

This means that you should write your code as cleanly and organized as possible, and it is likely that the compiler will do these optimizations for you. It is more important that your overall strategy for solving the problem is the most efficient than worry about performance of function calls.

别理我 2024-09-16 04:23:27

只需以最简单、结构最完善的方式编写代码,然后在编写和测试代码后,您可以对其进行分析,看看是否有任何需要优化的热点。只有在这一点上你才应该关心微观优化,如果你的编译器正在完成它的工作,这甚至可能没有必要。

Just write the code in the simplest and most well-structured way you can, then when you have it written and tested you can profile it to see if there are any hotspots which require optimisation. Only at that point should you concern yourself with micro-optimisations, and this may not even be necessary if your compiler is doing its job.

早乙女 2024-09-16 04:23:27

我刚刚花了一上午的时间调优一个由 C 和 Fortran 混合组成的应用程序,当然它使用了很多功能。我发现(以及我通常发现的)并不是函数很慢,而是某些函数调用(其中很少)实际上根本不需要执行 /em>。例如,清除内存块,只是为了整洁,但频率很高。

这不是语言的函数,也不是真正的内联函数。函数调用可能是免费,但您仍然会遇到调用树往往比必要的更加茂密的问题。你需要找出在哪里修剪它。 这是我的“分析”方法依赖。

无论你做什么,找出需要修复的地方。别猜。许多人并不认为这种问题是猜测,但当他们发现自己问“这有用吗?有帮助吗?”时,他们只是在摸索,而不是找出答案问题出在哪里。一旦他们知道问题出在哪里,解决办法就显而易见了。

I've just spent all morning tuning an app consisting of mixed C and Fortran, and of course it uses a lot of functions. What I found (and what I usually find) is not that functions are slow, but that certain function calls (and very few of them) don't really have to be done at all. For example, clearing memory blocks, just to be neat, but doing it at high frequency.

This is not a function of language, and not really a function of inlining either. Function calls could be free and you would still have the problem that the call tree tends to be more bushy than necessary. You need to find out where to prune it. This is the "profiling" method I rely on.

Whatever you do, find out what needs to be fixed. Don't Guess. Many people don't think of this kind of question as guessing, but when they find themselves asking "Will this work, will that help?", they're poking in the dark, rather than finding out where the problems are. Once they know where the problems are, the fix is obvious.

孤云独去闲 2024-09-16 04:23:27

通常,Fortran 中的子例程/函数调用的开销非常小。虽然语言标准没有指定参数传递机制,但典型的实现是“通过引用”,因此不涉及复制,仅设置一个新过程。在大多数现代架构中,这几乎没有什么开销。选择好的算法通常比微观优化重要得多。

关于调用 be fast 的一个例外可能是编译器必须创建临时数组的情况,例如,如果实际参数是非连续数组子部分,而被调用的过程参数是普通连续数组。假设虚拟参数是维度 (:)。使用维度 (:) 的数组调用它很简单。如果您在调用中请求非单位步幅,例如数组 (1:12:3),则该数组是不连续的,编译器可能需要创建一个临时副本。假设实际参数是维度 (:,:)。如果调用有数组 (:,j),则子数组是连续的,因为在 Fortran 中,第一个索引在内存中变化最快,并且不需要副本。但数组 (i,:) 是不连续的,可能需要临时副本。

有些编译器可以选择在需要临时数组副本时向您发出警告,以便您可以根据需要更改代码。

Typically subroutine / function calls in Fortran will have very little overhead. While the language standard doesn't specify argument passing mechanisms, the typical implementation is "by reference" so no copying is involved, only setting up a new procedure. On most modern architectures this has little overhead. Selecting good algorithms is generally far more important than micro-optimizations.

An exception about calling be quick could be case in which the compiler has to create temporary arrays, for example, if the actual argument is a non-contiguous array subsection and the called procedure argument is a plain contiguous array. Suppose that the dummy argument is dimension (:). Calling it with an array of dimension (:) is simple. If you request a non-unit stride in the call, e.g., array (1:12:3), then the array is non-contiguous and the compiler may need to create a temporary copy. Suppose that the actual argument is dimension (:,:). If the call has array (:,j), the sub-array is contiguous since in Fortran the first index varies fastest in memory and shouldn't need a copy. But array (i,:) is non-contiguous and might require a temporary copy.

Some compilers have options to warn you when temporary array copies are needed so that you can change your code, if you wish.

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