【问题标题】:Efficiently generating the set of all words of length n from an alphabet in Julia从 Julia 中的字母表中有效地生成长度为 n 的所有单词的集合
【发布时间】:2020-05-06 12:57:13
【问题描述】:

虽然类似问题已经发布在本网站上,但没有一个涉及 Julia 语言。我已经实现了该算法的工作版本,并且正在寻找针对特定语言的优化。

这是我用 Julia 编写的代码:

S(a::Array, n::Int64)::Array{Array} = n == 0 ? [[]] : vcat([push!.(deepcopy(S(a, n-1)), α) for α in a]...)

虽然此代码按预期工作,但速度很慢,而且消耗大量内存。

我已经尝试通过避免多次重新计算 S(a, n-1) 来稍微优化它:

S(a::Array, n::Int64)::Array{Array} = n == 0 ? [[]] : (arr::Array{Array} -> vcat([push!.(deepcopy(arr), α) for α in a]...))(S(a, n-1))

但是,内存效率低下的问题仍然存在。有什么方法可以优化此代码以提高内存效率?

【问题讨论】:

    标签: arrays optimization julia


    【解决方案1】:

    我认为以下内容可以满足您的要求。

    using Base.Iterators
    T(a,n) = product(repeated(a,n)...)
    

    这在几个方面更好。首先,它产生一个迭代器,因此大致不使用内存。其次,它是类型稳定的,而您编写的版本生成 eltype Any 的数组,这会使使用它的代码类型不稳定。

    此外,它的速度要快得多。

    julia> @time S([1,2,3,4,5,6,7,8,9], 6);
      1.767797 seconds (16.22 M allocations: 1.315 GiB, 20.28% gc time)
    
    julia> @time T([1,2,3,4,5,6,7,8,9], 6);
      0.000013 seconds (17 allocations: 576 bytes)
    
    julia> @time collect(T([1,2,3,4,5,6,7,8,9], 6));
      0.004837 seconds (20 allocations: 24.328 MiB)
    

    请注意,即使您收集结果以获得相同的答案(一个数组),它仍然快 400 倍以上并且分配的内存要少得多。

    【讨论】:

    • 谢谢,这就是我想要的!输出是一个多维数组,但我想可以使用reshape进行线性化?
    • 是的。从技术上讲,vec 可能更简洁,因为它基本上是重塑一维数组的简写。
    • 使用: 运算符删除维度,使其为collect(T([1,2,3,4,5,6,7,8,9], 3))[:] 甚至更好的view(collect(T([1,2,3,4,5,6,7,8,9], 3)),:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    相关资源
    最近更新 更多