generator - 试图找到一种方法来构造 Julia `generator`

标签 generator julia

我是 Julia 的新手。
我主要用python编程。

在 python 中,
如果你想迭代大量的值,
通常构造一个所谓的生成器来节省内存使用。
这是一个示例代码:

def generator(N):
    for i in range(N):
        yield i

我想知道 Julia 是否有类似的东西。
在阅读了 Julia 手册后,
@task 宏似乎与 python 中的生成器具有相同(或相似)的功能。
然而,
经过一些实验,
内存使用量似乎比 julia 中的普通数组大。

我用 @time在 IJulia 中查看内存使用情况。
这是我的示例代码:

[更新]:添加generator的代码方法
(generator 方法)
function generator(N::Int)
    for i in 1:N
        produce(i)
    end
end

(发电机版)
function fun_gener()
    sum = 0
    g = @task generator(100000)
    for i in g
        sum += i
    end
    sum
 end
@time fun_gener()耗时:0.420731828 秒(分配了 6507600 字节)

(阵列版)
function fun_arry()
    sum = 0
    c = [1:100000]
    for i in c
        sum += i
    end
    sum
end
@time fun_arry()耗时:0.000629629 秒(分配了 800144 字节)

谁能告诉我为什么@task在这种情况下需要更多空间吗?
如果我想在处理大量值时节省内存使用量,
我能做些什么?

最佳答案

我推荐 "tricked out iterators" Carl Vogel 的博文,详细讨论了 julia 的迭代器协议(protocol)、任务和协同例程。
另见 task-aka-coroutines在 Julia 文档中。

在这种情况下,您应该使用 Range 类型(它定义了 迭代器协议(protocol) ):

julia> function fun_arry()
           sum = 0
           c = 1:100000  # remove the brackets, makes this a Range
           for i in c
               sum += i
           end
           sum
       end
fun_arry (generic function with 1 method)

julia> fun_arry()  # warm up
5000050000

julia> @time fun_arry()
elapsed time: 8.965e-6 seconds (192 bytes allocated)
5000050000
分配的内存更快且更少(就像 python 2 中的 xrange 一样)。
来自博文的片段:

From https://github.com/JuliaLang/julia/blob/master/base/range.jl, here’s how a Range’s iterator protocol is defined:

start(r::Ranges) = 0
next{T}(r::Range{T}, i) = (oftype(T, r.start + i*step(r)), i+1)
next{T}(r::Range1{T}, i) = (oftype(T, r.start + i), i+1)
done(r::Ranges, i) = (length(r) <= i)

Notice that the next method calculates the value of the iterator in state i. This is different from an Array iterator, which just reads the element a[i] from memory.

Iterators that exploit delayed evaluation like this can have important performance benefits. If we want to iterate over the integers 1 to 10,000, iterating over an Array means we have to allocate about 80MB to hold it. A Range only requires 16 bytes; the same size as the range 1 to 100,000 or 1 to 100,000,000.



您可以编写生成器方法(使用任务):
julia> function generator(n)
          for i in 1:n      # Note: we're using a Range here!
              produce(i)
          end
       end
generator (generic function with 2 methods)

julia> for x in Task(() -> generator(3))
          println(x)
       end
1
2
3
注意:如果你用这个替换 Range,性能会差很多(并且分配更多的内存):
julia> @time fun_arry()
elapsed time: 0.699122659 seconds (9 MB allocated)
5000050000

关于generator - 试图找到一种方法来构造 Julia `generator`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29338914/

相关文章:

json - 使用类似 JSON 的结构遍历 Julia 中的嵌套字典

julia - 在包代码上使用 Infiltrator.jl 而无需将 Infitrator 添加到 Project.toml

python - 当未产生该值时,有没有办法更新生成器循环条件?

javascript - for循环中的函数发生器

python - 如何在python中的while循环语句中使用迭代器

julia - 从Julia脚本生成独立的可执行文件?

julia - 多个 ID 上的数据框连接

java - 顺序 key 生成器(java)

python - 生成器方法、深度复制和复制

julia - 为什么 Julia 中的 `where` 语法对换行敏感?