【问题标题】:Why does Fortran 90 compilation takes very long when large static array are initialized?为什么初始化大型静态数组时 Fortran 90 编译需要很长时间?
【发布时间】:2017-08-17 04:19:46
【问题描述】:

我需要在 Fortran 子程序中初始化一个静态数组

double precision A(56136,8)

像这样:

  A(1,1)=0.999950528145
  A(1,2)=0.99982470274
  A(1,3)=0.999987006187
  .
  .
  .
  A(56136,7)=0.933468163013
  A(56136,8)=0.0668926686049

后者是由另一个程序生成的。

使用 ifort 13.0 ifort file.f -O0 编译需要很长时间(大约 30 分钟)。

Q1:这是什么原因,我该如何避免?

我没有处理主程序,子程序链接到第三方文件。该子例程被非常频繁地调用,因此文件访问是不可取的。

Q2:是否可以将初始化放在子程序之外,不用主程序,避免每次调用子程序时进行初始化?

编辑

它是恒定的。在声明语句中初始化它会是这样的吗?

  double precision A(56136:8)=reshape(/*
 &             #, #, #, #, #, #, #, #,
 &             #, #, #, #, #, #, #, #,
 :
 &            */,(56136,8))

这不起作用,因为换行符太多。

【问题讨论】:

  • 因为编译器有很多工作要做。不能在声明语句中初始化吗?它是一个常数还是以后会改变?
  • 它是恒定的。在声明语句中初始化它看起来像这样?双精度 A(56136:8)=reshape(/* & #, #, #, #, #, #, #, #, & #, #, #, #, #, #, #, #, : & * /,(56136,8)) 对吗?
  • 这段代码很疯狂,它包含了将近 450,000 行的赋值语句。编译器可能会在 WTF ? 中惊呆了大约 25 分钟,然后才停下来继续工作。您确定不能修改代码以在第一次需要时从文件中读取值,并使用save 在调用之间保留它们吗?
  • 感谢大家的帮助。我通过从文件中读取一次数据并在 save 关键字的帮助下保存它来做到这一点。由于换行符(声明)过多或编译器工作过多(在代码中赋值),将其放入源代码中不起作用
  • 有什么地方可以让我安全地对 Fortran 大发雷霆吗? 几乎所有平均年龄在 60 岁以下的技术聚会(即几乎所有技术聚会)。我,我喜欢抱怨 Swift 和 .NET 以及其他玩具编程语言...

标签: arrays compilation fortran initialization


【解决方案1】:

我用 10000 个整数进行了测试,当使用 DATA 语句时,它可以在几秒钟内编译。我的数组包含 50000 个整数,但想看看我是否可以将它们分配为 10000 个块。

program Console1
implicit none
! Variables
integer A(50000)

data A(1:10000) / &       ! 1000 lines of 10 numbers each to follow:
      2,     3,     5,     7,    11,    13,    17,    19,    23,    29, &
     31,    37,    41,    43,    47,    53,    59,    61,    67,    71, &
     73,    79,    83,    89,    97,   101,   103,   107,   109,   113, &
    127,   131,   137,   139,   149,   151,   157,   163,   167,   173, &
    179,   181,   191,   193,   197,   199,   211,   223,   227,   229, &
    233,   239,   241,   251,   257,   263,   269,   271,   277,   281, &
...
 104087,104089,104107,104113,104119,104123,104147,104149,104161,104173, &
 104179,104183,104207,104231,104233,104239,104243,104281,104287,104297, &
 104309,104311,104323,104327,104347,104369,104381,104383,104393,104399, &
 104417,104459,104471,104473,104479,104491,104513,104527,104537,104543, &
 104549,104551,104561,104579,104593,104597,104623,104639,104651,104659, &
 104677,104681,104683,104693,104701,104707,104711,104717,104723,104729 /

! Append the first 10000 elements to the remaining array
A(10001:50000) = [A(1:10000),A(1:10000),A(1:10000),A(1:10000)]

print *, A(9998:10002)

end program Console1

编辑 1

这里是如何使用带有COMMON 块的DATA 语句来设置子例程中的值。请注意,几乎不推荐使用通用块。

subroutine A_Fill()
implicit none
integer :: A(10)
common /vals/ A
data A/ 1,2,3,4,5,6,7,8,9,10 /

end subroutine

program Console1
implicit none
! Variables
integer :: A(10)
common /vals/ A

call A_Fill()
print *, A

end program Console1

编辑 2

另一种使用函数将保存的数组复制到辅助工作副本的解决方案。

function A_Fill() result(B)
implicit none
integer :: B(10)
integer,save :: A(10)
data A/ 1,2,3,4,5,6,7,8,9,10 /
    B = A
end function

program Console1
implicit none   
interface 
    function A_Fill() result(B)
    implicit none
    integer :: B(10)
    end function        
end interface
! Variables
integer :: A(10)

A = A_Fill()    
print *, A

end program Console1

【讨论】:

  • 您对问题的评论(“您是否尝试过使用 DATA 语句,如果有太多行继续,则将其拆分为几个数组,稍后再组装。”)表明它可能是值得说明的是:可以使用多个数据语句来初始化单个数组。
  • @francescalus 是的,您可以使用DATA 语句仅初始化数组的一部分(就像我所做的那样)并链接多个语句以完全定义一个大数组。请参阅DATA 的文档以了解三个主要选项(按名称、按元素或按隐含的 do 循环)。
  • 我使用了另一种解决方案,但这回答了我的问题。只有一件事:在programsubroutine 中使用DATA 解决方案有什么不同吗?
  • @ChristianSchmidt - DATA 语句不能带有虚拟参数。您必须将它与模块变量或其他一些全局变量(如公共块)一起使用。
  • @ChristianSchmidt - 谢谢你的接受。我编辑了答案以显示如何使用子程序使用公共块填充值。
猜你喜欢
  • 2022-06-15
  • 1970-01-01
  • 1970-01-01
  • 2019-04-30
  • 1970-01-01
  • 1970-01-01
  • 2018-12-27
  • 1970-01-01
  • 2015-01-13
相关资源
最近更新 更多