Julia:多项分布随机数生成的内存分配优化问题
多项分布随机数生成的内存分配优化问题
先看你的测试代码:
pop = zeros(100) p = rand(100) p /= sum(p) # 假设下一行在循环内 @time pop = rand(Multinomial(100, p)) #test1 @time pop .= rand(Multinomial(100, p)) #test2
内存分配差异原因
- test1(2次分配):
rand(Multinomial(100, p))会生成一个新的Vector{Int}数组(1次分配),另外Multinomial分布实例初始化时会有一次小内存分配(用于存储分布参数的内部结构)。后续pop = ...只是把新数组的引用赋值给pop,无额外分配,所以累计2次。 - test2(4次分配):首先
rand(Multinomial(...))同样会产生新数组+分布实例的2次分配;接着.=广播赋值操作,Julia的广播机制会创建临时广播对象,同时过程中还有其他小的临时内存占用,这又带来2次分配,最终累计4次。核心是rand返回的临时数组本身就是一次分配,再加上广播的额外开销,导致分配次数多于test1。
0内存分配的实现方法
要实现0内存分配,直接用Distributions.jl提供的rand!方法,它能把生成的随机数直接写入预先分配好的数组,无需创建新数组:
# 预先分配数组(注意类型要匹配多项分布的输出类型Int) pop = zeros(Int, 100) p = rand(100) p /= sum(p) # 把分布实例移到循环外,避免每次循环重复初始化带来的小分配 dist = Multinomial(100, p) # 循环内执行 @time rand!(dist, pop)
这种方式下,循环内的rand!只会复用预先分配的pop数组,全程不会产生新的内存分配,完全适配循环内高频调用的场景。
内容的提问来源于stack exchange,提问作者Michele Avella
相关产品推荐
相关产品推荐

