2014-10-17 3 views
1

Я хотел бы написать таблицу с 1 целым числом, за которой следуют 3 удвоения в двоичном формате. Конечно, я могу просто сделать циклзаписать двоичный файл multiprecision с помощью matlab

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

, но это довольно медленно для массивов с несколько миллионов записей. Каков наиболее эффективный способ справиться с этим (без необходимости писать .mex)?

К сожалению, я должен поддерживать этот формат [int32 float64 float64 float64], так как это спецификация формата файла, используемая программой.

ответ

1

Edit: Так, наконец, самый быстрый способ сделать это и соблюдать точный порядок и тип переменной, чтобы преобразовать таблицу 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 

Это займет меньше времени, чтобы преобразовать их в целое, когда вы читаете их, чем вы потратили WR используя смешанные значения точности. Единственным недостатком этого метода является небольшое увеличение размера файла (~ около 14%).

+0

Благодарим за помощь!К сожалению, это уже существующий формат файла для чтения другими программами, которые требуют от меня написать [int32 float64 float64 float64]. Может быть, я могу создать байт по байтам и написать его за один раз? – serigado

+0

@serigado. Да, это последнее средство. Я надеялся, что вам не придется туда идти, но в самом деле ваш последний шанс состоял бы в том, чтобы конвертировать каждую «двойную» в 2 столбца _bit аналогичного_ 'int32', а затем« fwrite »всю таблицу за один раз. – Hoki

+0

Использование num2hex, разделение и применение hex2dec происходит медленнее, хотя это классно. Я не могу поверить, что нет возможности ускорить это. – serigado

Смежные вопросы