我有一个返回数组的函数。我想将函数映射到输入的向量,而输出则是所有数组的简单串联。该函数是:
function log_it(r, bzero = 0.25, N = 400)
main = rand(Float16, (N+150));
main[1] = bzero;
for i in 2:N+150
main[i] = *(r, main[i-1], (1-main[i-1]))
end;
y = unique(main[(N+1):(N+150)]);
r_vec = repeat([r], size(y)[1]);
hcat(r_vec, y)
end;
而且我可以很好地映射它:
map(log_it, 2.4:0.001:2.405)
但是结果很糟糕:
[2.4 0.58349609375]
[2.401 0.58349609375]
[2.402 0.583984375; 2.402 0.58349609375]
[2.403 0.583984375]
[2.404 0.583984375]
[2.405 0.58447265625; 2.405 0.583984375]
注意,嵌套数组的长度是无穷大的-我正在寻找一种不依赖于预先知道嵌套数组的长度的解决方案。
我想要的是这样的:
2.4 0.583496
2.401 0.583496
2.402 0.583984
2.402 0.583496
2.403 0.583984
2.404 0.583984
2.405 0.584473
2.405 0.583984
我使用了for循环:
results = Array{Float64, 2}(undef, 0, 2)
for i in 2.4:0.001:2.405
results = cat(results, log_it(i), dims = 1)
end
results
代码可以正常工作,但是for循环大约需要四倍的时间。我还觉得map是执行此操作的正确方法,而我只是缺少了一些东西-以执行map的方式来返回良好的数组向量,或者以某种“不必要的”方式对数组进行了更改。我尝试浏览诸如flatten和collect等功能,但找不到任何东西。
非常感谢!
您确定要正确设置基准吗?尤其是在运行非常快的情况下,基准测试有时会很棘手。首先,我建议确保始终将要进行基准测试的所有代码包装到一个函数中,并使用BenchmarkTools包来获取可靠的时序。
一般来说,在Julia中编写循环不应该降低性能,因此与map
相比,循环的运行时间增加了3倍,这听起来令人怀疑。
这是我得到的:
julia> using BenchmarkTools
julia> @btime map(log_it, 2.4:0.001:2.405)
121.426 μs (73 allocations: 14.50 KiB)
julia> function with_loop()
results = Array{Float64, 2}(undef, 0, 2)
for i in 2.4:0.001:2.405
results = cat(results, log_it(i), dims = 1)
end
results
end
julia> @btime with_loop()
173.492 μs (295 allocations: 23.67 KiB)
所以循环慢了大约50%,但这是因为您分配的更多。
[当您使用map
时,通常会使用另一种Julia方式来表达您在使用broadcasting时所做的事情。这适用于任何用户定义的函数:
julia> @btime log_it.(2.4:0.001:2.405)
121.434 μs (73 allocations: 14.50 KiB)
等效于您的map
表达式。我想您正在寻找的只是堆叠所有结果向量的一种方法-您可以使用vcat
并对其进行喷溅:
julia> @btime vcat(log_it.(2.4:0.001:2.405)...)
122.837 μs (77 allocations: 14.84 KiB)
仅用于确认:
julia> vcat(log_it.(2.4:0.001:2.405)...) == with_loop()
true
因此,使用广播和级联可以在map
解决方案的速度和内存成本上获得与循环相同的结果。