当阵列大于800,000,000时,我的Fortran筛子速度急剧降低

物理学家

我是物理学家,最近我一直在与Fortran合作。最初,我将Java广泛用于娱乐,因为它是我学习的第一门语言,但是我将其放弃用于Fortran和C ++。我对素数充满了业余爱好,因此创建了素数筛子。我能够在15秒内找到所有最高达2 ^ 31的质数。这是Java的最大数组大小,到此为止。我仔细地移植了代码(我是认真的说,我非常沮丧,我的代码太慢了,以至于我找不到错误,因此我将Fortran代码移植回Java以验证这不是我的错,然后将其移植回Java到Fortran,删除每次迭代!)。问题在于,大约有8亿台Fortran会停顿下来。到那时为止,它击败了Java,但之后却变得异常缓慢。我花了几个小时将其绘制并拟合曲线。它以指数的速度降低,可能需要数百年才能解决Java级别的问题。我问过很多人无济于事。为什么这发生在我身上?!?!有什么明智的Fortran编码员可以帮助我吗?我正在运行2013年下半年的Macbook Pro i5。我的代码如下。

program sieve
integer(4),allocatable:: prime(:)
integer(4)::a,max,b,primeCount
write(*,*)"Welcome to the slow prime number sieve!"
write(*,*)"--------------------------------------------"
write(*,*)"Up to what numbers do you need to find primes for?"
write(*,*)"Enter a number below 2^(32-1)"
read*, max

primeCount=0
allocate(prime(max))
prime(1)=1

    do a=2,int(sqrt(real(max))) !the main loop
        if(prime(a)==0)then !if the number is marked as prime procede
            do b=2*a,max,a  !eliminate all the numbers that are multiples of the number
                if(prime(b)==0)then !but only spend time eliminating if the number is still marked prime
                    prime(b)=1
                end if
            end do
        end if
    end do

do a=1,max
    if(prime(a)==0)then
        primeCount=primeCount+1
    end if
end do

print*, primeCount

end program

编辑:我的机器安装了4 Gig的ram

彼得

我可以看到您可以采取几种措施来加快代码的速度,尽管它们似乎都无法解释您所经历的性能急剧下降。罪魁祸首似乎是亚历山大·沃格特(Alexander Vogt)建议的RAM限制。

您应该做的第一件事是将primefrom更改integerlogicalarray。这减少了内存需求,并加快了的评估if (prime(a)==0)

代码的相关部分如下所示

logical(1),allocatable:: prime(:)

primeCount=0
allocate(prime(max))
prime = .false.
prime(1)=.true.

    do a=2,int(sqrt(real(max))) !the main loop
        if(.not. prime(a))then !if the number is marked as prime procede
            do b=2*a,max,a  !eliminate all the numbers that are multiples of the number
                if(.not. prime(b))then !but only spend time eliminating if the number is still marked prime
                    prime(b)=.true.
                end if
            end do
        end if
    end do

do a=1,max
    if(.not. prime(a))then
        primeCount=primeCount+1
    end if
end do

我没有做任何Java编程,但是在Matlab中,如果您声明prime(1:max)=0然后仅在21之间切换值01我会认为Matlab将数组视为logical数组。Java可能也在做同样的事情。这可以解释为什么您的Java代码不会遭受性能下降的影响(假定RAM约束确实是问题所在)。

编辑:我做了一些实验。

在我的机器(Debian Linux 64位,i3、16GB RAM,具有默认标志的ifort 14)上,花了22秒max=800 million (8E8)花费了60秒max=2E9这不是问题所报告的时间。同样在每种情况下,prime数组碰巧都初始化为零。

此外,使用integer(1)可使程序的运行速度比使用快33%integer(4)使用时logical(1),运行速度比使用时快5%integer(1)此行为可能是由于更好地使用现金所致,因为每个现金元素都prime占用较少的内存空间,因此处理器可以对当前的现金数据更快地循环进行更多次迭代。

我从中得出的结论是,罪魁祸首是亚历山大·沃格特(Alexander Vogt)指出的缺少RAM,并且作者的经验很可能不受初始化prime数组的遗漏的影响(尽管绝对不应该发生) ),就像HighPerformanceMark指出的那样。此外,我怀疑Java声明prime为逻辑数组,这就是为什么在那里没有发生问题的原因。(尽管在Java中仅15秒即可获得2 ^ 31的收益?这里使用的Fortran代码与此相距甚远。是否真的比较了相同的代码?)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

当我在sqlite中存储一个索引大于100,000的字节数组时,从表中选择它只能得到20的索引

AWS Boto sqs-为什么我不能发布大于196 000字节的消息?

如何降低我的CPU速度?

当卡塔尔分配了800,000个IP地址时,为什么要使用一个IP地址?

当我得到的值为 42,000 美元时,我如何比较并断言字符串大于 1000 美元。如何将此字符串转换为整数?

假设我的数据库中有一个+1,000,000,000,000,000的条目

VBScript 错误类型不匹配代码 800A000D

分割具有800,000列的文件

800A000D 格式不匹配 (VBS)

Intellisense降低我的计算机速度

在接近特定点时降低节点速度

不带小数且大于10,000的匹配数

从画布上截取大于20,000像素的屏幕截图

任何想法,使我的代码效率的循环10 000 000 000倍

当我尝试写入 100,000 条记录时出现 ProvisionedThroughputExceededException 错误

当运行bootrec.exe / rebuildbcd时,我仅获得windows.old.000 \ windows(Windows 7)

在 int 打印出达到 1,000,000 后 Python 速度变慢

Kotlin-我该如何以逗号分隔每三个数字1,000,000,000

我正在使用std :: bitset并尝试创建大小为100,000,000,000的两个数组std :: bitset

改善我对Eratosthenes筛子的实施

添加括号时子集data.table的速度降低

实体框架可在每个表上记录超过800,000条记录

大型参考文件(800,000行)。存储在数组中或使用文件句柄

解码函数并获取Microsoft VBScript运行时错误'800a000d'

为什么我的质数筛子返回相同结果的速度比在Python 2.7中查找质数的蛮力方法慢?

eZ 平台:当我尝试生成 GraphQL 架构时出现错误:“SQLSTATE[HY000] [2002] No such file or directory”

超时在数据库中插入1,000,000行(有时)

保持1,000,000个Websocket开放时,将占用多少系统资源?

制作大桌子(2'000'000 +)时程序停止工作