Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Matlab 我能用并行计算读取一个巨大的文本文件吗?_Matlab_File Io_Parallel Processing_Large Files - Fatal编程技术网

Matlab 我能用并行计算读取一个巨大的文本文件吗?

Matlab 我能用并行计算读取一个巨大的文本文件吗?,matlab,file-io,parallel-processing,large-files,Matlab,File Io,Parallel Processing,Large Files,我有多个大约2GB大小的文本文件(大约7000万行)。我还有一台四核机器,可以使用并行计算工具箱 通常,您可以打开一个文件并按如下方式读取行: f = fopen('file.txt'); l = fgets(f); while ~ isempty(l) % do something with l l = fgets(f); end 我想在我的4个内核中分发“Dosomething withl”,但这当然需要使用parfor循环。这需要我将2GB文件(借用Perl术语)预先“s

我有多个大约2GB大小的文本文件(大约7000万行)。我还有一台四核机器,可以使用并行计算工具箱

通常,您可以打开一个文件并按如下方式读取行:

f = fopen('file.txt');
l = fgets(f);
while ~ isempty(l)
    % do something with l
    l = fgets(f);
end
我想在我的4个内核中分发“Dosomething with
l
”,但这当然需要使用
parfor
循环。这需要我将2GB文件(借用Perl术语)预先“slurp”到MATLAB中,而不是动态处理。我实际上不需要
l
,只需要处理的结果

有没有一种方法可以通过并行计算从文本文件中读取行

编辑:值得一提的是,我可以提前找到准确的行数(
!wc-l mygiantfile.txt

EDIT2:文件结构如下:

15 1180 62444 e0e0 049c f3ec 104

3个十进制数,3个十六进制数,1个十进制数。对7000万行重复此操作。

一些matlab内置函数支持多线程-列表如下。没有必要使用并行计算工具箱

如果“用l做点什么”可以从工具箱中受益,那么在阅读另一行之前,只需实现该函数

您也可以使用以下命令读取整个文件:

fid = fopen('textfile.txt');
C  = textscan(fid,'%s','delimiter','\n');
fclose(fid);
然后并行计算C中的单元格


如果读取时间是一个关键问题,您可能还希望访问
parfor
循环中的部分数据文件。下面是一个来自中国的例子


根据要求,我将展示一个使用类的文件示例

由于您没有提供数据文件的确切格式,我将创建自己的数据文件。我正在创建的数据是一个由
N
行组成的表,每个行由4列组成:

  • 第一个是一个
    double
    标量值
  • 第二个是
    单个
  • 第三个是固定长度的字符串,用十六进制表示法表示
    uint32
    (例如:
    D091BB44
  • 第四列是
    uint8
生成随机数据并将其写入如上所述结构的二进制文件的代码:

% random data
N = 10;
data = [...
    num2cell(rand(N,1)), ...
    num2cell(rand(N,1,'single')), ...
    cellstr(dec2hex(randi(intmax('uint32'), [N,1]),8)), ...
    num2cell(randi([0 255], [N,1], 'uint8')) ...
];

% write to binary file
fid = fopen('file.bin', 'wb');
for i=1:N
    fwrite(fid, data{i,1}, 'double');
    fwrite(fid, data{i,2}, 'single');
    fwrite(fid, data{i,3}, 'char');
    fwrite(fid, data{i,4}, 'uint8');
end
fclose(fid);
以下是在十六进制编辑器中查看的结果文件:

我们可以确认第一条记录(注意,我的系统使用字节排序):


接下来,我们使用内存映射打开文件:

m = memmapfile('file.bin', 'Offset',0, 'Repeat',Inf, 'Writable',false, ...
    'Format',{
        'double', [1 1], 'd';
        'single', [1 1], 's';
        'uint8' , [1 8], 'h';      % since it doesnt directly support char
        'uint8' , [1 1], 'i'});
现在我们可以作为一个普通人:

好处是,对于大型数据文件,您可以将映射“查看窗口”限制为记录的一小部分,并沿文件移动此视图:

% read the records two at-a-time
numRec = 10;                       % total number of records
lenRec = 8*1 + 4*1 + 1*8 + 1*1;    % length of each record in bytes
numRecPerView = 2;                 % how many records in a viewing window

m.Repeat = numRecPerView;
for i=1:(numRec/numRecPerView)
    % move the window along the file
    m.Offset = (i-1) * numRecPerView*lenRec;

    % read the two records in this window:
    %for j=1:numRecPerView, m.Data(j), end
    m.Data(1)
    m.Data(2)
end

也许您可以将文件分成4个相等的部分,并使用
parfor
对其进行处理,每个核心上一个。。。我认为这仍然是IO限制的,所以旋转多个进程不会给您带来太多好处,除非“用l做点什么”部分真的是CPU密集型的。也许MATLAB也不是这项工作的最佳工具,如果文件是一个长的二进制向量,您可以使用
fscan
\
fread
parfor
并给出适当的指针。稍后我将尝试展示一个示例…@natan:下面是一个使用
fread
以矢量化方式读取结构化二进制文件的示例:非常好。。。。你得到了我的+1对于那些感兴趣的人,Loren Shure的博客上最近有一篇文章,展示了如何在计算机集群上执行大数据分析:你建议在内存中读取整个文件?我不明白这是怎么回答这个问题的。文件IO操作永远不会是多线程的。。。当文件变得比可用文件大时会发生什么RAM@Amro这正是我的想法——我希望避免提前“咕噜咕噜”整个文件。通过使用带循环的
textscan
可以轻松解决RAM问题:
对于k=1:nTimes,C=textscan(fid,'%s',nLines,'delimiter','\n');结束
因为它将保持当前文件位置,所以不会减慢进程。@沃纳:对,分块读取绝对是一个可行的解决方案。另一个选择是。我的观点是,所有这些都不容易并行化,这正是OP所要问的。@Amro很高兴听到这个
menmapfile
,不知道这个解决方案(x)。是的,我注意到你们对并行化的关注,但我不能回答这个问题,希望Magla能对此有所启发。我想说,并行化是没有意义的,因为即使文件在
n
不同的文件中分开,读取速度也将限制在磁盘读取速度。我认为最好的解决方案是一个线程读取,而其他线程正在处理已经读取的信息,但是同步会非常无聊。太棒了,谢谢!我将不得不根据我的需要进行调整,但这绝对是一个很好的开始。我只想提醒您,上述方法适用于具有固定长度字段和记录的二进制文件(我们提前知道每个字段的字节数和精度)。它不适用于空格分隔的文本文件,除非您使用某种填充使所有字段对齐。正确。我可能会回到这个文件的源代码,让他为我把它变成二进制格式。
m = memmapfile('file.bin', 'Offset',0, 'Repeat',Inf, 'Writable',false, ...
    'Format',{
        'double', [1 1], 'd';
        'single', [1 1], 's';
        'uint8' , [1 8], 'h';      % since it doesnt directly support char
        'uint8' , [1 1], 'i'});
>> rec = m.Data;      % 10x1 struct array

>> rec(1)             % same as: data(1,:)
ans = 
    d: 0.3257
    s: 0.1080
    h: [70 53 54 50 55 53 50 70]
    i: 192

>> rec(4).d           % same as: data{4,1}
ans =
    0.5799

>> char(rec(10).h)    % same as: data{10,3}
ans =
2B2F493F
% read the records two at-a-time
numRec = 10;                       % total number of records
lenRec = 8*1 + 4*1 + 1*8 + 1*1;    % length of each record in bytes
numRecPerView = 2;                 % how many records in a viewing window

m.Repeat = numRecPerView;
for i=1:(numRec/numRecPerView)
    % move the window along the file
    m.Offset = (i-1) * numRecPerView*lenRec;

    % read the two records in this window:
    %for j=1:numRecPerView, m.Data(j), end
    m.Data(1)
    m.Data(2)
end