【问题标题】:Padding an array with zeroes in fortran without using loops在fortran中用零填充数组而不使用循环
【发布时间】:2018-08-26 16:38:31
【问题描述】:

我有两个数组,我想比较它们的大小并将尾随零添加到较短的数组中。

eg- 对于数组 -

y1=(/ 1,2,3 /)
y2=(/ 1,2,3,4,5 /)

最后的结果应该是——

y1=(/ 1,2,3,0,0 /)
y2=(/ 1,2,3,4,5 /)

我对 Fortran 很陌生,据我所知,可以这样完成:-

integer, allocatable :: y1(:),y2(:)
integer :: l1,l2,i
.
.
.
! some code to generate y1 and y2 here
.
.
.
l1=size(y1)
l2=size(y2)

if (l1>l2) then
    do i=l2+1,l1
        y2(i)=0
    enddo
else if (l2>l1) then
    do i=l1+1,l2
        y1(i)=0
    enddo
endif

我想知道是否有更好的方法来做到这一点,最好是不涉及循环的方法,因为我正在处理的实际问题可能有巨大的向量

【问题讨论】:

  • 首先你必须重新分配较短的数组。可以分配吗?它是如何定义的?
  • 是的,它们是可分配的。我将编辑问题。我认为变量声明是不必要的
  • 请记住,在现代 Fortran 中(我认为是从 2003 年开始),您可以使用方括号数组构造函数,例如:y1=[ 1,2,3 ],而不是更旧的 (//)
  • 我不知道。谢谢你。我使用的是 f95 扩展。到现在为止我只知道这些
  • @Steve 好吧,分配的重新分配仍然是我的钱的重新分配。我在写评论时很清楚这种可能性。

标签: fortran gfortran fortran90 fortran95


【解决方案1】:

这是一种方法:

y1 = RESHAPE(y1,SHAPE(y2),pad=[0])

没有显式循环。正如@VladimirF 所评论的,较短的数组必须重新分配,这种方法将其留给编译器和运行时来处理。

如果您担心这种方法的性能,或者担心它的性能wrt使用显式循环的版本,并且担心性能如何随数组大小而变化,那么运行一些测试.如果发现显式重新分配和一两个循环比这种“聪明”的方法更快,我不会感到惊讶。

【讨论】:

  • 感谢您的回答。我还没有在任何真实数据集上测试过任何东西。不过谢谢你的建议。我将测试这两种方法,看看哪一种在性能方面更好
  • 这个答案正是我想要的,所以我认为我应该接受它。它完全符合我的要求,填充数组。可能还有其他方法,但这在技术上正是我所要求的。不过我会检查性能。
  • 我实际上对从 1000 到 50000000 的不同大小的数据集进行了测试,数组大小之间的差异从 10 到 9000000 不等。总的来说,在我的所有测试中,显式分配,释放和循环大约快 60%。
  • 感谢您的更新。它证实了我的一般观点,即显式循环比整洁的全数组替代方案更快,但拥有数据总是很好。
  • @Yuki.kuroshita:在 matlab、python/numpy、R 等许多解释型语言中,数组操作更快,因为这样可以避免显式循环的解释器开销。在 Fortran 中,它都被编译成机器码,所以你应该使用最清晰的。数组语法是天赐之物,它使许多常见的操作变得简单而简短,但你不需要为了避免跌入性能悬崖而做一些超级棘手的事情。如果一个算法更清楚地表达为一个显式循环,那就这样做吧。
【解决方案2】:

如果您只关心 1 级数组,则使用 SHAPERESHAPE 是多余的。只需使用 Fortran 的数组构造函数功能。您还可以使用现代 Fortran 的分配时分配功能,因此您无需重新分配较短的数组。

program foo
  implicit none
  integer, allocatable :: y1(:),y2(:)
  integer :: l1,l2,i
  y1 = [1, 2, 3]
  y2 = [1, 2, 3, 4, 5]
  l1 = size(y1)
  l2 = size(y2)
  if (l1 > l2) y2 = [y2, [(0,i=1,l1-l2)]]
  if (l2 > l1) y1 = [y1, [(0,i=1,l2-l1)]]
  print '(10(I0,1X))', y1
  print '(10(I0,1X))', y2
end program foo

【讨论】:

  • 还有一个更短的程序,可能需要更多的计算工作。删除 if (l1 > l2)if (l2 > l1)。生成的带有隐含执行循环的数组构造函数将做正确的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-25
  • 2023-03-28
  • 2020-09-11
  • 2014-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多