10 GB Daten? Das Aktualisieren von MAT-Dateien mit mehreren Variablen kann aufgrund des MAT-Format-Overheads teuer werden. Ziehen Sie in Betracht, die Daten aufzuteilen und jede Variable in einer anderen MAT-Datei zu speichern. Verwenden Sie bei Bedarf Verzeichnisse für die Organisation. Selbst wenn Sie eine praktische Funktion zum Löschen von Variablen aus einer MAT-Datei hätten, wäre dies ineffizient. Die Variablen in einer MAT-Datei sind zusammenhängend angeordnet, so dass das Ersetzen und Austauschen einer Variablen das Lesen und Schreiben eines Großteils des Rests erfordern kann. Wenn sie sich in separaten Dateien befinden, können Sie einfach die gesamte Datei löschen, was schnell geht.
Um dies in Aktion zu sehen, versuchen Sie diesen Code und durchlaufen Sie ihn im Debugger, während Sie etwas wie Process Explorer (unter Windows) verwenden, um seine E/A-Aktivität zu überwachen.
function replace_vars_in_matfile
x = 1;
% Random dummy data; zeros would compress really well and throw off results
y = randi(intmax('uint8')-1, 100*(2^20), 1, 'uint8');
tic; save test.mat x y; toc;
x = 2;
tic; save -append test.mat x; toc;
y = y + 1;
tic; save -append test.mat y; toc;
Auf meinem Computer sehen die Ergebnisse so aus.(Lesen und Schreiben sind kumulativ, Zeit pro Betrieb ist.)
Read (MB) Write (MB) Time (sec)
before any write: 25 0
first write: 25 105 3.7
append x: 235 315 3.6
append y: 235 420 3.8
Beachten Sie, dass die kleinen x variable Aktualisierung ist teurer als der großen y aktualisieren. Ein Großteil dieser E/A-Aktivität ist "redundante" Haushaltsarbeit, um das MAT-Dateiformat organisiert zu halten, und wird verschwinden, wenn jede Variable in ihrer eigenen Datei ist.
Versuchen Sie auch, diese Dateien auf dem lokalen Dateisystem zu behalten; es wird viel schneller sein als Netzlaufwerke. Wenn sie auf ein Netzlaufwerk zugreifen müssen, sollten Sie in Erwägung ziehen, die lokalen temporären Dateien save() und load() (möglicherweise mit tempname() ausgewählt) zu kopieren und dann auf das Netzlaufwerk zu kopieren. Das Speichern und Laden von Matlab ist bei lokalen Dateisystemen viel schneller, so dass das lokale Speichern/Laden und eine Kopie einen beträchtlichen Nettogewinn bedeuten.
Hier ist eine grundlegende Implementierung, mit der Sie Variablen in separaten Dateien mit den bekannten save() - und load() - Signaturen speichern können. Sie haben das Präfix "d", um anzuzeigen, dass es sich um die verzeichnisbasierten Versionen handelt. Sie benutzen ein paar Tricks mit evalin() und assignin(), also dachte ich, es wäre es wert, den vollständigen Code zu veröffentlichen.
function dsave(file, varargin)
%DSAVE Like save, but each var in its own file
%
% dsave filename var1 var2 var3...
if nargin < 1 || isempty(file); file = 'matlab'; end
[tfStruct,loc] = ismember({'-struct'}, varargin);
args = varargin;
args(loc(tfStruct)) = [];
if ~all(cellfun(@isvarname, args))
error('Invalid arguments. Usage: dsave filename <-struct> var1 var2 var3 ...');
end
if tfStruct
structVarName = args{1};
s = evalin('caller', structVarName);
else
varNames = args;
if isempty(args)
w = evalin('caller','whos');
varNames = { w.name };
end
captureExpr = ['struct(' ...
join(',', cellfun(@(x){sprintf('''%s'',{%s}',x,x)}, varNames)) ')'];
s = evalin('caller', captureExpr);
end
% Use Java checks to avoid partial path ambiguity
jFile = java.io.File(file);
if ~jFile.exists()
ok = mkdir(file);
if ~ok;
error('failed creating dsave dir %s', file);
end
elseif ~jFile.isDirectory()
error('Cannot save: destination exists but is not a dir: %s', file);
end
names = fieldnames(s);
for i = 1:numel(names)
varFile = fullfile(file, [names{i} '.mat']);
varStruct = struct(names{i}, {s.(names{i})});
save(varFile, '-struct', 'varStruct');
end
function out = join(Glue, Strings)
Strings = cellstr(Strings);
if length(Strings) == 0
out = '';
elseif length(Strings) == 1
out = Strings{1};
else
Glue = sprintf(Glue); % Support escape sequences
out = strcat(Strings(1:end-1), { Glue });
out = [ out{:} Strings{end} ];
end
Hier ist die Last() gleichwertig.
function out = dload(file,varargin)
%DLOAD Like load, but each var in its own file
if nargin < 1 || isempty(file); file = 'matlab'; end
varNames = varargin;
if ~exist(file, 'dir')
error('Not a dsave dir: %s', file);
end
if isempty(varNames)
d = dir(file);
varNames = regexprep(setdiff(ls(file), {'.','..'}), '\.mat$', '');
end
out = struct;
for i = 1:numel(varNames)
name = varNames{i};
tmp = load(fullfile(file, [name '.mat']));
out.(name) = tmp.(name);
end
if nargout == 0
for i = 1:numel(varNames)
assignin('caller', varNames{i}, out.(varNames{i}));
end
clear out
end
Dwhos() ist das Äquivalent von whos ('- Datei').
function out = dwhos(file)
%DWHOS List variable names in a dsave dir
if nargin < 1 || isempty(file); file = 'matlab'; end
out = regexprep(setdiff(ls(file), {'.','..'}), '\.mat$', '');
Und ddelete(), um die einzelnen Variablen zu löschen, wie Sie gefragt.
function ddelete(file,varargin)
%DDELETE Delete variables from a dsave dir
if nargin < 1 || isempty(file); file = 'matlab'; end
varNames = varargin;
for i = 1:numel(varNames)
delete(fullfile(file, [varNames{i} '.mat']));
end
+1 für clevere Problemumgehung! – Jonas