首页 > 解决方案 > 为什么用户定义的类型与 Julia 中的内置语言类型一样快速和紧凑?

问题描述

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

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

标签: julia

解决方案


这是一个难以准确回答并涵盖所有极端情况的问题。

这是我对一个简单(希望不要过于简化)的解释:

  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

现在,如果您运行@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)

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

但现在考虑以下定义:

struct C
    a
end

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

现在对这个函数进行基准测试给出:

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

原因 in type Cfielda可以保存任何值,因此编译器无法证明这x.a是一个Int并且因此必须做一些额外的工作。您可以通过检查@code_warntype f(C(1), 10^6).@code_warntype f(A(1), 10^6)


推荐阅读