执行时间 julia 程序计算素数

Execution time julia program to count primes

我正在对 julia 进行一些试验,因为我听说它适用于科学微积分,而且它的语法让人想起 python。我尝试编写并执行一个程序来计算低于某个 n 的素数,但性能不如预期。 在这里,我 post 我的代码,带有我昨天真正开始使用 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 是一种编译语言.发生什么事了?

以下是我的更改方式:

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,您想要递增计数器。这里不需要使用三元运算符 ? :


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

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)。使用此类值很慢,因为编译器无法使用任何优化来利用已处理的更具体类型的值。