arrays - Julia - 许多分配以浏览结构中的数组

标签 arrays struct julia allocation

我目前正在为 Julia 的奇怪行为而苦恼。 我正在浏览一个数组,无论该数组是否在结构内部,Julia 的行为都不一样。

在结构中的数组的情况下,有许多分配似乎毫无意义。具体来说,分配的数量与数组的大小一样多。

下面是重现此问题的代码:

function test1()
    a = ones(Float32, 256)

    for i = 1:256
        a[i]
    end
end

struct X
    mat
end

function test2()
    a = X(ones(Float32, 256))

    for i = 1:256
        a.mat[i]
    end
end

function main()
    test1()
    test2()

    @time test1()
    @time test2()
end

main()

我得到的输出:

0.000002 seconds (1 allocation: 1.141 KiB)
0.000012 seconds (257 allocations: 5.141 KiB)

一开始以为是类型问题,后来也没强求,循环后类型也没什么不同。

感谢您的帮助。

最佳答案

您需要在struct 中指定mat 的类型。否则,您使用 X 的函数将无法专门化和优化。

Fields with no type annotation default to Any, and can accordingly hold any type of value. https://docs.julialang.org/en/v1/manual/types/index.html#Composite-Types-1

将结构定义更改为

struct X
    mat::Vector{Float32}
end

将解决问题。 现在的结果是:

  0.000000 seconds (1 allocation: 1.141 KiB)
  0.000000 seconds (1 allocation: 1.141 KiB)

如果您更改代码中的一件事,您实际上可以通过 @code_warntype 宏看到效果。

for i = 1:256
    a.mat[i]
end

这部分并没有真正做太多。要查看 @code_warntype 的效果,请将旧代码中的这一行更改为

for i = 1:256
    a.mat[i] += 1.
end

@code_warntype 的结果将为 Any 提供红色,您通常应该避免这种情况。原因是 mat 的类型在编译时未知。

> @code_warntype test2() # your test2() with old X def
Body::Nothing
1 ─ %1  = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Float32,1}, svec(Any, Int64), :(:ccall), 2, Array{Float32,1}, 256, 256))::Array{Float32,1}
│   %2  = invoke Base.fill!(%1::Array{Float32,1}, 1.0f0::Float32)::Array{Float32,1}
└──       goto #7 if not true
2 ┄ %4  = φ (#1 => 1, #6 => %14)::Int64
│   %5  = φ (#1 => 1, #6 => %15)::Int64
│   %6  = (Base.getindex)(%2, %4)::Any <------ See here
│   %7  = (%6 + 1.0)::Any
│         (Base.setindex!)(%2, %7, %4)
│   %9  = (%5 === 256)::Bool
└──       goto #4 if not %9
3 ─       goto #5
4 ─ %12 = (Base.add_int)(%5, 1)::Int64
└──       goto #5
5 ┄ %14 = φ (#4 => %12)::Int64
│   %15 = φ (#4 => %12)::Int64
│   %16 = φ (#3 => true, #4 => false)::Bool
│   %17 = (Base.not_int)(%16)::Bool
└──       goto #7 if not %17
6 ─       goto #2
7 ┄       return

现在使用 X 的新定义,您将在 @code_warntype 的结果中看到推断出每种类型。

您可能想使用 Parametric Types如果您希望 X.mat 保存其他类型的 Vector 或值。使用参数类型,编译器仍然能够优化您的函数,因为类型在编译期间是已知的。我真的建议您阅读 types 的相关手册条目和 performance tips .

关于arrays - Julia - 许多分配以浏览结构中的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54923957/

相关文章:

javascript - 在 Javascript 中,如何在 "joined"数组周围加上单引号?

c - 在结构体内部使用结构体

c - 如何释放递归结构(trie)

C 编程 : store getchar as a char array

c++ - 如何在 .h 和 .cpp 中为类中的私有(private)字符数组编写 get 函数?

c++ - 获取结构C++中元素的索引

julia - Turing.jl 估计器显示提案将因数值错误而被拒绝

struct - 调用参数结构的构造函数时发生方法错误

julia - 如何绘制两个直方图之间的差异? ( Julia )

javascript - Angular ng-options 复杂的 json 数组