使用Julia Mmap复制一个巨大的文件

问题描述 投票:0回答:1

我有一个大文件(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
julia memory-mapped-files
1个回答
1
投票

我知道了!解决方案是按块(大约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)

感谢所有的评论让我这样做。

=====编辑=====

为了进一步阅读,你可能会看:

提供有关一次复制的最佳块大小的提示。

© www.soinside.com 2019 - 2024. All rights reserved.