julia - 使用 Julia Mmap 复制一个大文件
问题描述
我有一个大文件(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)
感谢所有在评论中引导我这样做的人。
===== 编辑 =====
如需进一步阅读,您可以查看:
它给出了一次复制的最佳块大小的提示。
推荐阅读
- python - 如何从从字符串读取的包中导入模块?
- python - 在 Python 中读取文件时遇到问题
- apache-spark - Cassandra 加入后解析 Spark RDD
- c++ - 在使用 Visual Studio 进行调试时,我的应用程序在外部 DLL 调用上冻结。如何找到此 DLL 的路径?
- metadata - PDF 搜索结果中的旧元数据
- ios - 无法在警报 SwiftUI 中格式化文本
- ios - 如何配置 Mailgun 以与 Sign in with Apple 和 Apple 的中继服务一起使用?
- amazon-web-services - 使用 nodeJs 将文件上传到 s3 存储桶而不使用 AWS 控制台
- python - 如何将列分隔符添加到 Pandas 数据框显示
- python - 不同模型的训练精度不同,但测试精度相同