Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 如何优化函数并最小化分配_Performance_Fortran_Dynamic Memory Allocation - Fatal编程技术网

Performance 如何优化函数并最小化分配

Performance 如何优化函数并最小化分配,performance,fortran,dynamic-memory-allocation,Performance,Fortran,Dynamic Memory Allocation,以下函数生成的素数最多为N。对于较大的N,这会变得非常缓慢,对于N=10**7,我的Julia实现速度快了5倍。我想创建一个大整数数组并使用pack收集结果是最慢的部分。我尝试先计算.true.s,然后分配res(:)并使用循环填充它,但在这种情况下,当我迭代prims数组两次时,加速比可以忽略不计(4%)。在《朱莉娅》中,我使用了findall,这正是我所做的;迭代数组两次,首先计算trues并分配结果,然后填充它。有什么想法吗?多谢各位 编译器: 英特尔(R)Visual Fortran英特

以下函数生成的素数最多为
N
。对于较大的
N
,这会变得非常缓慢,对于
N=10**7
,我的Julia实现速度快了5倍。我想创建一个大整数
数组
并使用
pack
收集结果是最慢的部分。我尝试先计算
.true.
s,然后分配
res(:)
并使用循环填充它,但在这种情况下,当我迭代
prims
数组两次时,加速比可以忽略不计(4%)。在《朱莉娅》中,我使用了
findall
,这正是我所做的;迭代数组两次,首先计算trues并分配结果,然后填充它。有什么想法吗?多谢各位

编译器: 英特尔(R)Visual Fortran英特尔(R)64编译器,适用于在英特尔(R)64上运行的应用程序,版本18.0.3.210构建20180410(在Windows 10上)

选项:
ifort-warn/O3-堆数组:8000000

program main
    implicit none
    integer, allocatable :: primes(:) 
    integer :: t0, t1, count_rate, count_max

    call system_clock(t0, count_rate, count_max)
    primes = do_primes(10**7)
    call system_clock(t1)

    print '(a,f7.5,a)', 'Elapsed time: ', real(t1-t0)/count_rate, ' seconds'
    print *, primes(1:10)

contains 

    function do_primes(N) result (res)
        integer, allocatable :: res(:), array(:) 
        logical, allocatable :: prims(:)
        integer :: N, i, j

        allocate (prims(N))
        prims = .true.
        i = 3
        do while (i * i < N) 
            j = i 
            do while (j * i < N)
                prims(j*i) = .false.
                j = j + 2
            end do
            i = i + 2
        end do 
        prims(1) = .false.
        prims(2) = .true.
        do i = 4, N, 2  
            prims(i) = .false.
        end do

        allocate (array(N)) 
        do i = 1, N 
            array(i) = i 
        end do 
        res = pack(array, prims)
    end 
end 
实施过程:

function do_primes(N)
    prims = trues(N)
    i = 3
    while i * i < N
        j = i 
        while j * i < N
            prims[j*i] = false
            j = j + 2
        end
        i = i + 2
    end 
    prims[1] = false
    prims[2] = true
    prims[4:2:N] .= false  
    return findall(prims) 
end

当您说“我想创建一个大整数数组并使用pack收集结果是最慢的部分”时,您是否实际分析了代码?我原以为嵌套循环是花费时间最多的部分。为什么只做while而不是直接的do循环?我的理解是后者提供了更多的优化机会。只是我看到嵌套循环在算法中是必不可少的,无法避免,所以对我来说最明显的事情就是避免不必要地创建一个大数组来打包结果。
do while
对于内环是方便的,因为终止条件是
j*ii如果嵌套环占用所有的时间,则通过优化组件无法获得速度提升。请使用分析器运行代码,并告诉我们哪些部分需要时间。然后,也只有到那时,你才知道该把精力集中在哪里。我将从正确实施埃拉托斯琴斯筛算法开始,你做了太多茱莉亚似乎用在prims上的不必要的工作,这可能有助于提高速度(只是猜测…)。如果我将prims=trues(N)改为prims=fill(true,N),那么在我的mac电脑上,代码的速度会慢约2倍(这接近于我用修改过的fortran代码所能得到的速度)。FWIW,我在Python+中尝试了类似的代码,然后经过的时间大约是Julia的x3(带位数组)和gfortran-10的x1.5。此外,Julia和Numba使用LLVM,因此差异可能与LLVM与GCC有关(只是猜测…)当您说“我猜创建一个大整数数组并使用pack收集结果是最慢的部分”时,您是否实际分析了代码?我原以为嵌套循环是花费时间最多的部分。为什么只做while而不是直接的do循环?我的理解是后者提供了更多的优化机会。只是我看到嵌套循环在算法中是必不可少的,无法避免,所以对我来说最明显的事情就是避免不必要地创建一个大数组来打包结果。
do while
对于内环是方便的,因为终止条件是
j*ii如果嵌套环占用所有的时间,则通过优化组件无法获得速度提升。请使用分析器运行代码,并告诉我们哪些部分需要时间。然后,也只有到那时,你才知道该把精力集中在哪里。我将从正确实施埃拉托斯琴斯筛算法开始,你做了太多茱莉亚似乎用在prims上的不必要的工作,这可能有助于提高速度(只是猜测…)。如果我将prims=trues(N)改为prims=fill(true,N),那么在我的mac电脑上,代码的速度会慢约2倍(这接近于我用修改过的fortran代码所能得到的速度)。FWIW,我在Python+中尝试了类似的代码,然后经过的时间大约是Julia的x3(带位数组)和gfortran-10的x1.5。此外,Julia和Numba使用LLVM,因此差异可能与LLVM与GCC有关(只是猜测…)
function do_primes(N)
    prims = trues(N)
    i = 3
    while i * i < N
        j = i 
        while j * i < N
            prims[j*i] = false
            j = j + 2
        end
        i = i + 2
    end 
    prims[1] = false
    prims[2] = true
    prims[4:2:N] .= false  
    return findall(prims) 
end
using Benchmarktools 
@benchmark do_primes(10^7)
BenchmarkTools.Trial:
  memory estimate:  6.26 MiB
  allocs estimate:  5
  --------------
  minimum time:     32.227 ms (0.00% GC)
  median time:      32.793 ms (0.00% GC)
  mean time:        34.098 ms (3.92% GC)
  maximum time:     94.479 ms (65.46% GC)
  --------------
  samples:          147
  evals/sample:     1