我有一个大文件(75GB)内存映射在一个数组d
,我想复制到另一个m
。因为我没有75GB的RAM,所以我做了:
for (i,v) in enumerate(d)
m[i] = v
end
为了复制值后的文件值。但是我在SSD上获得了大约2MB / s的复制速率,我希望在读取和写入时至少达到50MB / s。
我怎样才能优化此复制率?
=== [编辑] ===
根据评论,我将代码更改为以下内容,将写入速率提高到15MB / s
function copydcimg(m::Array{UInt16,4}, d::Dcimg)
m .= d
Mmap.sync!(m)
end
copydcimg(m,d)
此时,我认为我应该优化Dcimg代码。该二进制文件由间隔时间戳的帧组成。这是我用来访问框架的代码:
module dcimg
using Mmap
using TOML
struct Dcimg <: AbstractArray{UInt16,4} # struct allowing to access dcimg file
filename::String # filename of the dcimg
header::Int # header size in bytes
clock::Int # clock size in bytes
x::Int
y::Int
z::Int
t::Int
m # linear memory map
Dcimg(filename, header, clock, x, y, z, t) =
new(filename, header, clock, x, y, z, t,
Mmap.mmap(open(filename), Array{UInt16, 3},
(x*y+clock÷sizeof(UInt16), z, t), header)
)
end
# following functions allows to access DCIMG like an Array
Base.size(D::Dcimg) = (D.x, D.y, D.z, D.t)
# skip clock
Base.getindex(D::Dcimg, i::Int) =
D.m[i + (i ÷ (D.x*D.y))*D.clock÷sizeof(UInt16)]
Base.getindex(D::Dcimg, x::Int, y::Int, z::Int, t::Int) =
D[x + D.x*((y-1) + D.y*((z-1) + D.z*(t-1)))]
# allowing to automatically parse size
function Dcimg(pathtag)
p = TOML.parsefile(pathtag * ".toml")
return Dcimg(pathtag * ".dcimg",
# ...
)
end
export Dcimg, getframe
end
我知道了!解决方案是按块(大约1024×720 UInt16)复制文件块。这样我达到300MB / s,我甚至不知道单线程可能。这是代码。
在模块dcimg中,我添加了逐帧访问文件的方法
# get frame number n (starting form 1)
getframe(D::Dcimg,n::Int) =
reshape(D.m[
D.x*D.y*(n-1)+1 + (n-1)*D.clock÷sizeof(UInt16) : # cosmetic line break
D.x*D.y*n + (n-1)*D.clock÷sizeof(UInt16)
], D.x, D.y)
# get frame for layer z, time t (starting from 1)
getframe(D::Dcimg,z::Int,t::Int) =
getframe(D::Dcimg,(z-1)+D.z*(t-1))
迭代循环中的帧
function copyframes(m::Array{UInt16,4}, d::Dcimg)
N = d.z*d.t
F = d.x*d.y
for i in 1:N
m[(i-1)*F+1:i*F] = getframe(d, i)
end
end
copyframes(m,d)
感谢所有的评论让我这样做。
=====编辑=====
为了进一步阅读,你可能会看:
提供有关一次复制的最佳块大小的提示。