快速在Matlab中加载大块二进制文件

时间:2018-08-20 20:22:28

标签: matlab performance binaryfiles

我有一些非常大的数据文件(256通道,大约为75-100百万个样本=每个文件约40-50 GB),并采用int16格式。它以平面二进制格式编写,因此结构类似于:CH1S1,CH2S1,CH3S1 ... CH256S1,CH1S2,CH2S2,...

我需要分别读取每个通道,对其进行滤波和偏移校正,然后保存。我当前的瓶颈是加载每个频道,大约需要7-8分钟的时间...将其扩展到256倍,而我正在花将近30个小时来加载数据!我试图智能地使用fread,以在读取每个通道时跳过字节;我在所有256个通道中循环执行以下代码来做到这一点:

offset = i - 1;
fseek(fid,offset*2,'bof');
dat = fread(fid,[1,nSampsTotal],'*int16',(nChan-1)*2);

仔细阅读,这通常是加载大型二进制文件中某些部分的最快方法,但是文件太大而无法更快地执行此操作吗?

我没有加载太多数据...我正在使用的测试文件为37GB,对于256个通道之一,我仅为整个跟踪加载149MB ...也许是“跳过” fread的功能不是最理想的吗?

系统详细信息:MATLAB 2017a,Windows 7、64位,32GB RAM

1 个答案:

答案 0 :(得分:3)

@CrisLuengo的想法要快得多:本质上是对数据进行分块,加载每个块,然后将其拆分为单独的通道文件以节省RAM。

这里有一些代码仅用于加载部分,速度不到1分钟:

% fake raw data
disp('building... ');
nChan = 256;
nSampsTotal = 10e6;
tic; DATA = rand(nChan,nSampsTotal); toc;
fid = fopen('rawData.dat','w');
disp('writing flat binary file... ');
tic; fwrite(fid,DATA(:),'int16'); toc;
fclose(fid);

% compute the number of samples and chunks
chunkSize = 1e6;
nChunksTotal = ceil(nSampsTotal/chunkSize);


%% load by chunks
t1 = tic;
fid = fopen('rawData.dat','r');
dat = zeros(nChan,chunkSize,'int16');
chunkCnt = 1;
while 1
    tic
    if chunkCnt <= nChunksTotal
        % load the data
        fprintf('Chunk %02d/%02d: loading... ',chunkCnt,nChunksTotal);
        dat = fread(fid,[nChan,chunkSize],'*int16');
    else
        break;
    end
    toc;
    chunkCnt = chunkCnt + 1;
end
t = toc(t1); fprintf('Total time: %4.2f secs.\n\n\n',t);
% Total time: 55.07 secs.
fclose(fid);

另一方面,通过跳过文件来按频道加载大约需要20倍的时间,大约需要20多分钟:

%% load by channels (slow)
t1 = tic;
fid = fopen('rawData.dat','r');
dat = zeros(1,nSampsTotal);
for i = 1:nChan
    tic;
    fprintf('Channel %03d/%03d: loading... ');
    offset = i-1;
    fseek(fid,offset*2,'bof');
    dat = fread(fid,[1,nSampsTotal],'*int16',(nChan-1)*2);
    toc;
end
t = toc(t1); fprintf('Total time: %4.2f secs.\n\n\n',t);
% Total time: 1133.48 secs.
fclose(fid);

我还要感谢Matlab论坛上的OCDER:link