让x = randn(100, 2)
。我想将x
写入自己的文件。此文件将包含x
,只有x
和x
只能是Matrix{Float64}
类型。在过去,我总是使用HDF5
来解决这个问题,但是我发现这是过度杀戮,因为在这个设置中我每个文件只有一个数组。请注意,JLD
使用HDF5
,因此也会过度杀死。
1)假设我只想阅读整个矩阵,最快的读写方法是什么x
?
2)假设我可能想要读取矩阵的一部分,读取和写入x
的最快方法是什么?
3)读取和写入x
的最快方法是什么,假设我可能想要读取矩阵的切片,或者覆盖矩阵的切片(但< em>不改变矩阵大小)?
答案 0 :(得分:3)
您可以使用serialize
功能,只要您注意文档中有关版本之间的非保证等的警告。
serialize(stream :: IO,value)
以不透明的格式将任意值写入流,以便可以通过反序列化来回读它。回读值与原始值尽可能相同。一般来说,如果阅读和写作是由不同的完成,这个过程将不起作用 Julia的版本,或具有不同系统映像的Julia的实例。 Ptr值被序列化为全零位模式(NULL)。
首先将8字节标识头写入流。要避免编写标头,请构造一个SerializationState并将其用作序列化的第一个参数。另请参见Serializer.writeheader。
实际上,JLD(或者事实上,它的继任者JLD2)通常是推荐的方式*。
*您特别感兴趣的是:“JLD2以包含HDF5子集的格式保存和加载Julia数据结构,而不依赖于HDF5 C库”并且“它通常优于以前的JLD包(有时通过多个数量级),并且通常优于Julia的内置序列化器”。
答案 1 :(得分:1)
Julia有两个内置函数readdlm
&amp; writedlm
执行此操作:
julia> x = randn(5, 5)
5×5 Array{Float64,2}:
-1.2837 -0.641382 0.611415 0.965762 -0.962764
0.106015 -0.344429 1.40278 0.862094 0.324521
-0.603751 0.515505 0.381738 -0.167933 -0.171438
-1.79919 -0.224585 1.05507 -0.753046 0.0545622
-0.110378 -1.16155 0.774612 -0.0796534 -0.503871
julia> writedlm("txtmat.txt", x, use_mmap=true)
julia> readdlm("txtmat.txt", use_mmap=true)
5×5 Array{Float64,2}:
-1.2837 -0.641382 0.611415 0.965762 -0.962764
0.106015 -0.344429 1.40278 0.862094 0.324521
-0.603751 0.515505 0.381738 -0.167933 -0.171438
-1.79919 -0.224585 1.05507 -0.753046 0.0545622
-0.110378 -1.16155 0.774612 -0.0796534 -0.503871
绝对不是最快的方式(如果性能是一个大问题,DanGetz在评论中建议直接使用Mmap.mmap
,但似乎这是最简单的方法,输出文件是人类可读的。
答案 2 :(得分:0)
根据上面的Tasos提出的建议,我使用4种不同的方法对写入和读取进行了基本的速度测试:
serialize
和deserialize
)我已将测试代码粘贴在此答案的底部。结果是:
julia> @time f_write_test(N, "h5")
0.191555 seconds (2.11 k allocations: 76.380 MiB, 26.39% gc time)
julia> @time f_write_test(N, "jld")
0.774857 seconds (8.33 k allocations: 77.058 MiB, 0.32% gc time)
julia> @time f_write_test(N, "slz")
0.108687 seconds (2.61 k allocations: 76.495 MiB, 1.91% gc time)
julia> @time f_write_test(N, "dat")
0.087488 seconds (1.61 k allocations: 76.379 MiB, 1.08% gc time)
julia> @time f_read_test(N, "h5")
0.051646 seconds (5.81 k allocations: 76.515 MiB, 14.80% gc time)
julia> @time f_read_test(N, "jld")
0.071249 seconds (10.04 k allocations: 77.136 MiB, 57.60% gc time)
julia> @time f_read_test(N, "slz")
0.038967 seconds (3.11 k allocations: 76.527 MiB, 22.17% gc time)
julia> @time f_read_test(N, "dat")
0.068544 seconds (1.81 k allocations: 76.405 MiB, 59.21% gc time)
因此,对于写入,写入二进制选项的性能甚至优于serialize
,速度是HDF5
的两倍,几乎比JLD2
快一个数量级。
对于读取,deserialize
具有最佳性能,而HDF5
,JLD2
和二进制读取的性能相当接近,HDF5
略微领先。< / p>
我还没有考虑过写切片的测试,但将来可能会回到这里。显然,使用serialize
无法写入切片(更不用说serialize
也面临的版本控制/系统图像问题),而且我不确定如何使用{{1} }。我的直觉是,如果切片在磁盘上是连续的,则将切片写入二进制文件将轻松击败JLD2
,但如果它是非连续的和,则可能明显慢于HDF5
如果HDF5
方法最佳地利用分块。如果HDF5
没有利用分块(这意味着在写入时知道你想要什么样的切片),那么我怀疑二进制方法将会提前出现。
总之,我会采用二元方法,因为我认为在这个阶段它显然是整体胜利者。
我怀疑最终,HDF5
可能是选择的方法,但是有一个公平的方法可以去(这里的包本身很新,因此社区没有多少时间进行优化等)
测试代码如下:
JLD2