为什么用户定义的类型与Julia中的内置语言类型一样快速和紧凑?

Ant*_*ota 1 julia

我已经审查了很多文档,但我找不到具体的答案.

Julia标准基元类型都是在语言本身中定义的,Julia允许您声明自己的基元类型,但我不知道这是否是程序员定义的类型与内置类型一样快速和紧凑的原因.我甚至检查了GitHub上的源代码,更具体地说是bool.jl ,这是定义数值类型为int的地方,但我不敢做出推测.有人可以给我一个具体的答案吗?谢谢.

Bog*_*ski 6

这是一个难以回答的问题,涵盖所有角落案例.

以下是我对简单(希望不过分简化)解释的看法:

  1. Julia代码被编译为下一次执行的本机程序集指令.
  2. 如果Julia编译器能够证明两个实现是等价的,那么你可以期望为它们两者生成相同的本机汇编指令(它不是100%真实,但它是我的经验的一个很好的近似).
  3. 这意味着在本机程序集级别,只要您要执行的操作和类型信息编译器具有相同的内容,您使用的类型(内置或您自己的)并不重要.

这是一个简短的例子(我正在使用a,struct但这与你自己的原始类型相同):

struct A
    a::Int
end

function f(x::Int, n)
    s = Int[]
    for i in 1:n
        push!(s,x)
    end
    s
end

function f(x::A, n)
    s = Int[]
    for i in 1:n
        push!(s,x.a)
    end
    s
end

function f2(x::A, n)
    s = A[]
    for i in 1:n
        push!(s,x)
    end
    s
end
Run Code Online (Sandbox Code Playgroud)

现在,如果你运行的@code_native f(1, 10^6),@code_native f(A(1), 10^6)以及@code_native f2(A(1), 10^6)你将看到生成的代码是(几乎)相同.

您可以在基准测试中看到这种效果:

julia> using BenchmarkTools

julia> @btime f(1, 10^6);
  8.567 ms (20 allocations: 9.00 MiB)

julia> @btime f(A(1), 10^6);
  8.528 ms (20 allocations: 9.00 MiB)

julia> @btime f2(A(1), 10^6);
  8.446 ms (20 allocations: 9.00 MiB)
Run Code Online (Sandbox Code Playgroud)

您具有相同的时间和相同的分配数量.

但现在考虑以下定义:

struct C
    a
end

function f(x::C, n)
    s = Int[]
    for i in 1:n
        push!(s,x.a)
    end
    s
end
Run Code Online (Sandbox Code Playgroud)

现在对此功能进行基准测试可以

julia> @btime f(C(1), 10^6);
  19.855 ms (21 allocations: 9.00 MiB)
Run Code Online (Sandbox Code Playgroud)

在类型C字段中a可以保存任何值的原因,因此编译器无法证明这x.a是一个因此Int而必须做一些额外的工作.您可以验证这是通过检查的情况下@code_warntype f(C(1), 10^6)反对@code_warntype f(A(1), 10^6).