运行julia功能的巨大内存分配?

Abo*_*mar 2 performance julia

我尝试在julia命令中运行以下函数,但是在对函数进行计时时,我看到了太多的内存分配,我无法弄清楚为什么.

function pdpf(L::Int64, iters::Int64)
snr_dB = -10 
snr = 10^(snr_dB/10) 
Pf = 0.01:0.01:1      
thresh = rand(100)
Pd     = rand(100)

for m = 1:length(Pf)
    i = 0
    for k = 1:iters 
        n = randn(L) 
        s = sqrt(snr) * randn(L) 
        y = s + n 

        energy_fin = (y'*y) / L
        @inbounds thresh[m] = erfcinv(2Pf[m]) * sqrt(2/L) + 1

        if energy_fin[1] >= thresh[m]
            i += 1   
        end
    end
    @inbounds Pd[m] = i/iters
end

#thresh = erfcinv(2Pf) * sqrt(2/L) + 1
#Pd_the = 0.5 * erfc(((thresh - (snr + 1)) * sqrt(L)) / (2*(snr + 1)))

end
Run Code Online (Sandbox Code Playgroud)

在我的笔记本电脑上的julia命令中运行该功能,我得到以下令人震惊的数字:

julia> @time pdpf(1000, 10000)
 17.621551 seconds (9.00 M allocations: 30.294 GB, 7.10% gc time)
Run Code Online (Sandbox Code Playgroud)

我的代码出了什么问题?任何帮助表示赞赏.

Mic*_*gge 7

我不认为这种内存分配是如此令人惊讶.例如,考虑内循环执行的所有时间:

for m = 1:length(Pf) 这给你100次执行

for k = 1:iters 这会根据您提供给函数的参数为​​您提供10,000次执行.

randn(L) 这将根据您提供给函数的参数为​​您提供长度为1,000的随机向量.

因此,仅考虑这些,您就会生成100*10,000*1000 = 10亿个Float64随机数.它们中的每一个都需要64位= 8个字节.即8GB就在那里.而且,你有两个电话,randn(L)这意味着你已经有16GB的分配.

然后你有y = s + n另外8GB的分配,最高可达24GB.我没有仔细查看剩余的代码,以便从24GB到30GB的分配,但这应该表明GB分配开始在代码中添加并不困难.

如果你正在寻找需要改进的地方,我会给你一个暗示,通过使用普通随机变量的属性可以改善这些行:

    n = randn(L) 
    s = sqrt(snr) * randn(L) 
    y = s + n 
Run Code Online (Sandbox Code Playgroud)

您应该可以通过这种方式轻松地将此处的分配从24GB减少到8GB.请注意,y在您定义它时,这将是一个正常的随机变量,并想出一种方法来生成一个与y现在相同的正态随机变量.

另一件小事,snr就是你的功能内部不变.然而,你继续sqrt分开100万次.在某些情况下,"检查您的工作"可能会有所帮助,但我认为您可以确信计算机将在第一时间正确运行,因此您无需让它继续进行此计算; ).还有其他类似的地方你可以改进你的代码,以避免重复计算,我将留给你找到.