剧透程序:测试程序没有对结果做任何事情,所以优化编译器删除了循环的内容,因此每次运行都不需要同样的时间。无论如何,我会让问题和答案保留下来,以防有人(我?)同样的错误(再次.)。
原始文章:,我想测试与简单的加法相比,计算平方根的速度要慢多少,并编写了下面的小程序。我得到的结果是,在这种情况下,大约需要同样的时间,0.3秒。这里发生什么事情?
program sqtest
implicit none
real r, s
integer i,j,n, sq, t
sq=11
n=100000000
r=1.11
if (sq==1) then
do i = 1,n
s = sqrt(float(i)*r)
enddo
write(*,*) "squareroot"
else
do j = 1,n
t = j+4
enddo
write(*,*) "plus"
endif
end program将sq=1放置为使用平方根。平方根循环aso进行乘法和从int到float的转换。
发布于 2016-06-24 14:21:03
在进行这样的测试时,有很多事情要考虑。首先,你必须清楚地定义你在比较什么。对于这样简单的测试,您还应该禁用优化,大多数主要编译器都接受选项-O0来禁用优化。否则,编译器会发现您没有对计算值执行任何操作,甚至没有运行您的循环,因为它是无用的。
为了缩短它的长度,我修改了你的程序,使之
program sqtest
implicit none
real r0, r1, r2, s
integer i,n
real :: start, finish
n=10**9
call random_number(r0)
call random_number(r1)
call random_number(r2)
call cpu_time(start)
do i = 1,n
s = sqrt(r0)
enddo
call cpu_time(finish)
print '("SQRT: Time = ",f6.3," seconds.")',finish-start
call cpu_time(start)
do i = 1,n
s = r1+r2
enddo
call cpu_time(finish)
print '("Addtition: Time = ",f6.3," seconds.")',finish-start
end program它给出了我的系统的以下结果:
ifort 13, n = 10^8
SQRT: Time = 0.378 seconds
Addtition: Time = 0.202 seconds
ifort 13, n = 10^9
SQRT: Time = 3.460 seconds
Addtition: Time = 1.857 seconds
gfortran (GCC) 4.9, n = 10^8
SQRT: Time = 0.385 seconds
Addtition: Time = 0.191 seconds
gfortran (GCC) 4.9, n = 10^9
SQRT: Time = 3.529 seconds
Addtition: Time = 1.733 seconds
pgf90 14, n = 10^8
SQRT: Time = 0.380 seconds
Addtition: Time = 0.058 seconds
pgf90 14, n = 10^9
SQRT: Time = 3.438 seconds
Addtition: Time = 0.520 sec您将注意到,我在代码中调用CPU时间。要使数字有意义,您应该多次运行每一种情况,并计算时间平均值或选择最小值。最小值是接近系统在最优条件下所能达到的目标。您还将看到结果依赖于编译器。pgf90显然给出了更好的加法结果。我从平方根中删除了float(i)*。gfortran和pgf90的执行速度非常快(~ 2.6秒,n= 10^9),而ifort执行得非常慢(n=10^9为7.3秒)。这意味着gfortran和pgf90在那里选择了不同的路径(更快的操作),也许他们做了一些优化,即使我禁用了它?
发布于 2016-06-24 14:17:22
您将在本文档中找到硬件平方根的成本:tables.pdf。
可以用不同的方法计算sqrt。一般来说,它是一个迭代过程,只涉及加和乘操作。通常,sqrt被计算为sqrt(x) =x* (1/ sqrt(x) ),因为(1/sqrt(x))可以比sqrt(X)更快地计算。
如果使用Haswell CPU,单个SQRTSS指令的延迟时间为单精度11个周期,双精度16个周期(SQRTSD)。在单精度情况下,与双精度相比,收敛到期望精度所需的迭代次数较少。在同一个CPU上,有一个大约的sqrt (RSQRTSS)版本,延迟为一个周期,所以如果您请求积极的优化,编译器可以选择生成这个指令。
如果您需要多个独立的平方根,如您的示例所示,编译器可以自动将代码向量化。存在向量化变体VSQRTPS,其交互吞吐量为14。在这种情况下,平均为14/8 =每sqrt 1.75个周期。
参考文献:
发布于 2016-06-24 10:30:09
也许您的编译器正在优化代码。你可以用n(例如1e6,1e7,1e8,…,1e10)的不同数量级来测试这一点,看看时间尺度是如何变化的。顺便说一句,您的机器/编译器上允许的整数范围是多少?
https://stackoverflow.com/questions/38011140
复制相似问题