【问题标题】:Execution time julia program to count primes执行时间 julia 程序计算素数
【发布时间】:2022-01-21 09:01:23
【问题描述】:

我正在用 julia 做一些实验,因为我听说它适用于科学微积分,而且它的语法让人想起 python。我试图编写并执行一个程序来计算低于某个 n 的素数,但性能并不理想。 在这里,我发布了我的代码,其中包含我昨天在 julia 编程中真正开始的免责声明,我几乎可以肯定有些地方出了问题:

n = 250000
counter = 0

function countPrime(counter)
    for i = 1:n
        # print("begin counter= ", counter, "\n")
        isPrime = true
        # print("i= ", i, "\n")
        for j = 2:(i-1)
            if (i%j) == 0 
                isPrime = false
            #   print("j= ", j, "\n")
                break
            end
            
        end

        (isPrime==true) ? counter += 1 : counter
    #   print("Counter= ", counter, "\n")
    end
    return counter
end

println(countPrime(counter))

事实上,移植到 C 中的同一个程序大约需要 5 秒的执行时间,而在 julia 中的这个程序大约需要 3 分 50 秒,这听起来很奇怪,因为我认为 julia 是一种编译语言。发生了什么事?

【问题讨论】:

    标签: performance julia execution-time


    【解决方案1】:

    这是我将如何改变它:

    function countPrime(n)
        counter = 0
        for i in 1:n
            isPrime = true
            for j in 2:i-1
                if i % j == 0 
                    isPrime = false
                    break
                end            
            end
            isPrime && (counter += 1)
        end
        return counter
    end
    

    这段代码在我的笔记本电脑上运行大约 5 秒。除了风格变化之外,主要变化是您应该将n 作为参数传递给您的函数,并在您的函数中定义counter 变量。

    这些更改遵循 Julia 手册的 Performance Tips 部分中的第一个建议。

    关键是当你使用一个全局变量时,Julia 编译器无法对这个变量的类型做出假设(因为它可能在函数编译后改变),所以它防御性地假设它可能是任何东西,这会减慢速度。

    至于风格变化,请注意(isPrime==true) ? counter += 1 : counter 可以写成isPrime && (counter += 1),因为如果isPrimetrue,你想增加计数器。这里不需要使用三元运算符? :


    给出一个在函数中使用全局变量的问题:

    julia> x = 10
    10
    
    julia> f() = x
    f (generic function with 1 method)
    
    julia> @code_warntype f()
    MethodInstance for f()
      from f() in Main at REPL[2]:1
    Arguments
      #self#::Core.Const(f)
    Body::Any
    1 ─     return Main.x
    

    您可以看到,在f 函数内部,您引用了全局变量x。因此,当 Julia 编译 f 时,它必须假定 x 的值可以具有任何类型(在 Julia 中调用 Any)。使用这些值很慢,因为编译器无法使用任何可以利用处理的更具体类型的值的优化。

    【讨论】:

    • 谢谢,但我不明白为什么这会提高性能
    • 从 Bogumils 的解释或他链接的 Julia 性能提示中,您有什么不明白的地方?要查看代码的类型不稳定性以及 Bogumils 变体中不存在这种不稳定性,请将 @code_warntype countPrime(counter)(您的变体)的输出与 @code_warntype countPrime(n) 进行比较。注意所有Anys,以红色突出显示,表示类型不稳定。
    • 顺便说一句,我不推荐它,但为了论证,您还可以包装整个代码(ncounter 的初始化、countPrimes 的定义和countPrimes(counter) 调用)到一个,比如说,main() 函数。这也将解决不稳定性(因为 ncounter 现在是局部变量)。
    • @carstenbauer 这不是关于非常量全局变量而不是标准类型不稳定性吗?顺便说一句,我更喜欢counter += isPrime
    • 可以通过声明类型来实现加速吗?
    猜你喜欢
    • 2011-11-20
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    • 2021-07-15
    • 2018-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多