使用函数SPREAD和普通do循环之间的执行时间差异

时间:2014-07-24 19:33:41

标签: fortran

我想调查一下普通do循环和函数传播之间执行时间的差异。我问每个方法重复填充一个相同的较短阵列的长数组。用于此目的的代码显示在下面的文本中。但是,我一直收到一条错误消息,指出存在堆栈溢出。谁能让我知道我的代码有什么问题?谢谢,

... 
integer, dimension(:), allocatable :: long_ray,short_ray 
integer, dimension(:,:), allocatable :: box_ray          
integer :: i, long1, short1
long1 = 100000000
short1 = 100

allocate(long_ray(long1),short_ray(short1),box_ray(short1,long1/short1))
long_ray = [((i),i=1,long1)]
short_ray = [((i),i=1,short1)]
call system_clock(t1)
do i = 1,long1/short1
    long_ray((i-1)*short1+1:i*short1) = short_ray(:)
enddo
call system_clock(t2)
print*,'1 time: ',t2-t1

call system_clock(t1)
box_ray = spread(short_ray,2,long1/short1)
long_ray = reshape(box_ray, shape(long_ray))
call system_clock(t2)
print*,'2 time: ',t2-t1  
...

编辑添加:嗯,我弄清楚为什么我的程序不起作用(在Visual Studio 2012中使用英特尔Visual Fortran 2013的桌面上)。这个错误是由于我省略了解除其中一个阵营的错误。

我将long_ray添加到我未包含在我的代码片段中的行中: deallocate(int_array,short_array,box_ray),程序终于有效了。

顺便说一下,我发现,当 long1 的大小不超过10 ^ 8时,第一个代码块(普通的do-loop)的执行时间远远小于SPREAD函数块的那个。我是否可以声称在重新填充长序列时,do-loop优于SPREAD?

2 个答案:

答案 0 :(得分:2)

该程序在gfortran中为我工作,但在英特尔Fortran中并不适用。您可以使用-heap-arrays n强制ifort在堆上分配数组,其中n是KB的限制。我使用200。它可以使一些计算更慢,你已经尝试和测量。

答案 1 :(得分:1)

您的程序溢出堆栈,因为您没有足够的堆栈空间。

编译器经常将与表达式求值关联的临时对象放在堆栈上。程序中有许多这样的表达式,包括分配后的数组构造函数以及稍后的传播和重新整形引用。给定long1的值和整数的典型大小 - 您的某些表达式可能需要~0.4 GB的堆栈空间。这很多,特别是相对于一个主要平台上的默认堆栈大小限制只有1 MB。

如果您缩小long1的大小并确保您的程序有足够的堆栈分配,那么您的代码段对我有用。

编辑添加:请注意,智能优化器可能会注意到正在定义的数组未被使用 - 因此不会执行定义它们的代码。

相关问题