本地可分配数组和自动数组之间的区别 [英] Difference between local allocatable and automatic arrays

查看:248
本文介绍了本地可分配数组和自动数组之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对以下摘录中的 alloc_array automatic_array 之间的区别感兴趣:

 子程序mysub(n)
整数,意图(in):: n
整数:: automatic_array(n)
integer,allocatable :: alloc_array(:)

allocate(alloc_array(n))
... [code] ...

对于分配的基础知识(对高级技术没有太多的了解),我知道分配允许您更改代码中间的数组大小(正如这个问题),但我有兴趣考虑您不需要来更改数组大小的情况;它们可能会被传递到其他子程序进行操作,但代码和任何子程序中这两个变量的唯一目的是保存维数 n 的数组的数据(也许改变数据,但不是大小)。



(1)内存使用情况有任何不同吗?我不是专家但我对他们如何重要以及他们如何影响更高级别的编程(我所说的一种经验:一旦尝试在fortran中运行一个大代码,我得到一个错误,我没有不明白,系统管理员告诉我哦,是的,你可能已经饱和了堆栈,尝试在你的运行脚本中添加这行代码;任何让我深入了解如何在实际编码时考虑这些事情,以后不必修补它们欢迎)。有人告诉我,它可能依赖于许多其他的东西,比如编译器或者架构,但是我从那些回应中解释,他们并不完全确定这是怎么回事。它是否完全依赖于多种因素,或者是否存在编码中的默认/预期行为,然后可能会被可选的编译关键字或系统偏好所忽略?



同样,不是专家,但在我之前发生了这种情况,因为我声明了子例程的变量,所以最终我不得不把模块中的子例程。我已经知道这可能会有所不同,这取决于我是否使用对可分配变量特殊的东西。我正在考虑如何使用allocatables和automatics来完成我对变量所做的所有事情,而不是有意使用任何特定的allocatables(除了使用前的分配情况)。


$最后,如果这是有用的:,我所要求的理由是因为我们正在开发一个小组,最近我们注意到不同的人以不同的方式使用这两个声明,我们需要确定这是否可以留给个人偏好,或者是否有任何理由来设定明确的标准(以及如何设置标准)是一个好主意。我不需要非常详细的答案,我试图确定这是我应该做的研究,以便小心研究我们如何使用它以及应该在哪些方面进行研究。



尽管我有兴趣知道有趣的技巧,而不是与分配有关的事情,但与具有规模可变性的需求没有直接关系,我将离开这些人,在这里重点讨论严格的功能差异(意思是:我明确告诉编译器如何处理我的代码)。我提到的两个项目是我可以根据以前的经验提出的,但是我错过了并且应该考虑的其他重要的项目,请确实提及。

解决方案

为了清楚起见,我将简要提及术语。这两个数组都是局部变量和等级为1的数组。




  • alloc_array 是一个可分配数组;
  • automatic_array 是一个显式形状的自动对象。



同样在链接问题中,在分配语句之后,两个数组的大小都是 n 。我会在这里回答这些仍然是两个完全不同的东西。当然,可分配数组可以改变其分配状态并移动其分配。我会把这两个(大部分)都留在这个答案的范围之外。当然,一个可分配数组一旦定义就不需要改变这些东西。



内存使用量



以前对这个问题的修订引起了部分争议,这是因为内存使用的概念是多么不明确。作为一个标准,Fortran告诉我们两个数组的大小相同,它们将具有相同的存储布局,并且都是连续的。除此之外,还有很多您可能会听到的术语: 评论你表达了对ifort的兴趣。所以我不会走得太远,我会坚持使用那个编译器和提示考虑什么。



通常,ifort会将自动对象和数组临时堆栈。有一个(默认)编译器选项 -no-heap-arrays 被描述为有效



使用替代选项编译器将自动数组和临时数组放入堆栈存储区。 -heap-arrays 允许我们稍微控制一下:


这个选项会为临时创建的自动数组和数组计算堆栈而不是堆栈。

有可能控制堆栈/堆栈将被选择的大小阈值(当这在编译时是已知的):


如果编译器在编译时无法确定大小,它总是将自动数组放在因为 n 不是一个常量表达式,所以一个表达式就是一个表达式。 会希望你的数组 automatic_array 在这个选项上堆在堆上,不管指定的大小。



可能还有更多要说的,但如果我尝试过,这可能会太长。



接口需求

子例程 mysub :局部变量对此没有影响。任何调用它的程序单元都会对隐式接口感到满意。你问的是如何使用两个本地数组。



这主要取决于两个数组可以使用的用途。



如果第二个过程的伪参数具有allocatable属性,那么只有可分配数组可以传递给该过程。它还需要有一个明确的界面。无论程序是否改变分配,这都是真的。



当然,两个数组都可以作为参数传递给没有allocatable属性的哑参数,无论如何,为什么当分配状态没有变化等时,为什么要将一个参数传递给一个可分配的虚拟元素???????????b

有很好的理由:


  • 在程序中可能存在代码路径,它具有分配更改(例如由交换机控制) ;

  • 可分配的虚拟参数也传递边界;
  • 等等,


如果该子程序具有规格,则第二个更明显b
$ b $子程序mysub(n)
integer,intent(in):: n
integer :: automatic_array(2:n + 1)
整数,allocatable :: alloc_array(:)

allocate(alloc_array(2 :n + 1))

最后,自动对象的尺寸条件非常严格。 n 这里显然是允许的,但在配置是唯一合理的方式之前,事情不必太复杂。取决于有多少人愿意玩 block 结构。



还有IanH的评论:如果我们有一个非常大的 n 自动对象很可能导致崩溃。在可分配的情况下,可以使用 stat = 选项与编译器运行时达成某种友好的一致。


I am interested in the difference between alloc_array and automatic_array in the following extract:

subroutine mysub(n)
integer, intent(in)  :: n
integer              :: automatic_array(n)
integer, allocatable :: alloc_array(:)

allocate(alloc_array(n))
...[code]...

I am familiar enough with the basics of allocation (not so much on advanced techniques) to know that allocation allows you to change the size of the array in the middle of the code (as pointed out in this question), but I'm interested in considering the case where you don't need to change the size of the array; they might be passed onto other subroutines for operation, but the only purpose of both variables in the code and any subroutine is to hold the data of an array of dimension n (and maybe change the data, but not the size).

(1) Is there any difference in memory usage? I am not an expert in low level procedures, but I have a very slight knowledge of how they matter and how they can impact on the higher level programming (kind of experience I'm talkng about: once trying to run a big code in fortran I was getting a mistake I didn't understand, sysadmin told me "oh, yeah, you are probably saturating the stack; try adding this line in your running script"; anything that gives me insight into how to consider this things when actually coding and not having to patch them later is welcomed). I've been told by people that it might be dependent on many other things like compiler or architecture, but I interpreted from those responses that they were not completely sure of exactly how this was so. Is it so absolutely dependant on a multitude of factors or is there a default/intended behavior in the coding that may then be over-riden by optional compiling keywords or system preferences?

(2) Would the subroutines have different interface needs? Again, not an expert, but it had happened to me before that because of the way I declare variables of subroutine, I end up having to put the subroutines in a module. I've been given to understand this may vary depending on whether I use things that are special for allocatable variables. I am thinking about the case in which everything I do with the variables can be done both by allocatables and automatics, not intentionally using anything specific of allocatables (other than allocation before usage, that is).

Finally, in case this is of use: the reason I am asking is because we are developing in a group and we have recently noticed different people use those two declarations in different ways and we needed to determine if this is something that can be left to personal preference or if there might be any reasons why it might be a good idea to set a clear criteria (and how to set that criteria). I don't need extremely detailed answers, I am trying to determine if this is something I should be doing research about to be careful on how we use it and in what aspects of it should the research be directed.

Though I would be interested to know of "interesting tricks" than can be done with allocation but are not directly related to the need of having size variability, I am leaving those for a possible future follow-up question and focusing here on the strictly functional differences (meaning: what I am explicitly telling compilers to do with my code). The two items I mentioned are the thing I could come up with due to previous experiences, but any other important one that I am missing and should consider, please do mention them.

解决方案

For the sake of clarity, I'll briefly mention terminology. Of the two arrays both are local variables and arrays of rank 1.

  • alloc_array is an allocatable array;
  • automatic_array is an explicit-shape automatic object.

Again as in the linked question, after the allocation statement both arrays are of size n. I'll answer here in that these are still two very different things. Of course, the allocatable array can have its allocation status changed and its allocation moved. I'll leave both of those (mostly) out of the scope of this answer. An allocatable array, of course, needn't have these things changed once it's defined.

Memory usage

What was partly contentious about a previous revision of the question is how ill-defined the concept of memory usage is. Fortran, as a standard, tells us that both arrays come to be the same size and they'll have the same storage layout, and are both contiguous. Beyond that, much follows terms you'll hear a lot: implementation specific, processor dependent.

In a comment you expressed interest in ifort. So that I don't wander too far, I'll just stick with that one compiler and prompt of what to consider.

Often, ifort will place automatic objects and array temporaries onto stack. There is a (default) compiler option -no-heap-arrays described as having effect

The compiler puts automatic arrays and temporary arrays in the stack storage area.

Using the alternative option -heap-arrays allows one to control that slightly:

This option puts automatic arrays and arrays created for temporary computations on the heap instead of the stack.

There is a possibility to control size thresholds for which heap/stack would be chosen (when that is known at compile-time):

If the compiler cannot determine the size at compile time, it always puts the automatic array on the heap.

As n isn't a constant expression, then, one would expect your array automatic_array to be on the heap with this option, regardless of the size specified.

There's probably more to be said, but this could be far too long if I tried.

Interface needs

There is nothing special about the interface requirements of the subroutine mysub: local variables have no impact on that. Any program unit calling that would be happy with an implicit interface. What you are asking about is how the two local arrays can be used.

This largely comes down to what uses the two arrays can be put to.

If the dummy argument of a second procedure has the allocatable attribute then only the allocatable array here can be passed to that procedure. It will also need to have an explicit interface. This is true whether or not the procedure changes the allocation.

Of course, both arrays could be passed as arguments to a dummy argument without the allocatable attribute and then we don't have different interface requirements.

Anyway, why would one want to pass an argument to an allocatable dummy when there will be no change in allocation status, etc.? There are good reasons:

  • there may be a code path in the procedure which does have an allocation change (controlled by a switch, say);
  • allocatable dummy arguments also pass bounds;
  • etc.,

This second one is more obvious if the subroutine had specification

subroutine mysub(n)
integer, intent(in)  :: n
integer              :: automatic_array(2:n+1)
integer, allocatable :: alloc_array(:)

allocate(alloc_array(2:n+1))

Finally, an automatic object has quite strict conditions on its size. n here is clearly allowed, but things don't have to be much more complicated before allocation is the only plausible way. Depending on how much one wants to play with block constructs.

Taking also a comment from IanH: if we have a very large n the automatic object is likely to lead to crash-and-burn. With the allocatable, one could use the stat= option to come to some amicable agreement with the compiler run-time.

这篇关于本地可分配数组和自动数组之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆