用matlab编写multiprecision二进制文件

时间:2014-10-17 17:22:53

标签: matlab binary fwrite

我想写一个包含1个整数的表,然后是二进制格式的3个双精度表。 当然我可以做一个for循环

for i=1:sz
  fwrite(fid, integ(i), 'int');
  fwrite(fid, doubl(i,:), 'double');
end

但是对于具有几百万个条目的数组来说这是非常慢的。 处理此问题的最有效方法是什么(无需编写.mex)?

不幸的是我必须保留这个[int32 float64 float64 float64]格式,因为这是程序使用的文件格式规范。

1 个答案:

答案 0 :(得分:1)

修改 所以最后做到这一点并且尊重变量的确切顺序和类型的最快方法是将nx3 double的表转换为(2xn)x3 int32的数组,重新整形并连接数组然后一次性写入所有内容。

outfile4 = 'test1.bin' ;
tic4 = tic ;

% // reshape everything
table2write = int32(zeros(2*nCol+1,nPt)) ;
table2write(1,:) = integ.' ; %'
for k=1:nCol
   ixLine = (k-1)*2+2 ; 
   table2write( ixLine:ixLine+1 , : ) = reshape( typecast(doubl(:,k),'int32') , 2 , [] ) ;
end
% // write
fid = fopen( outfile4 , 'w' ) ;
count = fwrite(fid , table2write , 'int32' ) ;
fclose( fid ) ;
elapsed4 = toc(tic4)

结果如下:

elapsed4 =
   0.794346687070910

阅读下面的内容,了解测试变量的定义和稍快的方法,但会使数组变形


原始回答:
如果你有能力重新组织你的文件,你可以获得大量的时间。

考虑以下示例:

outfile1 = 'E:\TEMP\Z_ToDelete\test1.bin' ;
outfile2 = 'E:\TEMP\Z_ToDelete\test2.bin' ;

nPt = 0.5e6 ;
integ = int32( randi(32000,nPt,1) ) ;
doubl = rand(nPt,3) ;

%% // Write to file with mixed precision
tic1 = tic ;
fid = fopen( outfile1 , 'w' ) ;
for k = 1:nPt
  fwrite(fid, integ(k), 'int');
  fwrite(fid, doubl(k,:), 'double');
end
fclose( fid ) ;
elapsed1 = toc(tic1)

%% // write to file sequentially
tic2 = tic ;
fid = fopen( outfile2 , 'w' ) ;
fwrite(fid, integ, 'int');
fwrite(fid, doubl, 'double');
fclose( fid ) ;
elapsed2 = toc(tic2)

在我的系统上,此输出:

elapsed1 =
          19.7780466501241
elapsed2 =
        0.0309073378234669

因此,让Matlab处理完整数组的编写,一次一个精度比逐行指定要写的内容更有效。

缺点是从您保存的文件中读取一条记录可能会稍微复杂一些,但您可以轻松编写一个函数,对于给定的索引将会读取integer,跳过其余部分然后阅读3x doubles


如果您真的无法承担多路复用/多路分解数据的费用,那么您可以考虑将int转换为double并编写完整数组:

tic3 = tic ;
A = [double(integ) doubl] ;
fid = fopen( outfile2 , 'w' ) ;
fwrite(fid, A, 'double');
fclose( fid ) ;
elapsed3 = toc(tic3)

这仍然比最初的"混合精度"更快。溶液

elapsed3 =
         0.483094789081886

在读取它们时,将它们转换为整数将花费更少的时间,而不是用于编写混合精度值。这种方法的唯一缺点是文件大小略有增加(约14%)。