2010-05-21 3 views
2

J'essaie de traiter un très grand ensemble de données. J'ai k = ~ 4200 matrices (tailles variables) qui doivent être comparées de manière combinatoire, en sautant des comparaisons non-uniques et auto. Chacune des comparaisons k (k-1)/2 produit une matrice, qui doit être indexée par rapport à ses parents (c'est-à-dire qui peut trouver d'où elle vient). Le moyen pratique de le faire est de remplir (triangulairement) un tableau de cellules k par k avec le résultat de chaque comparaison. Ce sont en moyenne ~ 100 X ~ 100 matrices. En utilisant des flotteurs de précision simple, il fonctionne à 400 Go globalement.
Je dois 1) générer le tableau de cellules ou des morceaux de celui-ci sans essayer de placer le tout en mémoire et 2) accéder à ses éléments (et leurs éléments) de la même manière. Mes tentatives ont été inefficaces en raison de la dépendance sur MATLAB eval() ainsi que save et clear survenant dans les boucles.Algorithmes de mémoire insuffisante pour l'adressage de grandes baies

for i=1:k 
    [~,m] = size(data{i}); 
    cur_var = ['H' int2str(i)]; 
    %# if i == 1; save('FileName'); end; %# If using a single MAT file and need to create it. 
    eval([cur_var ' = cell(1,k-i);']); 
    for j=i+1:k 
     [~,n] = size(data{j}); 
     eval([cur_var '{i,j} = zeros(m,n,''single'');']); 
     eval([cur_var '{i,j} = compare(data{i},data{j});']); 
    end 
    save(cur_var,cur_var); %# Add '-append' when using a single MAT file. 
    clear(cur_var); 
end 

L'autre chose que je l'ai fait est d'effectuer la scission quand mod((i+j-1)/2,max(factor(k(k-1)/2))) == 0. Cela divise le résultat en le plus grand nombre de pièces de même taille, ce qui semble logique. L'indexation est un peu plus compliquée, mais pas trop mauvaise car un index linéaire pourrait être utilisé.

Est-ce que quelqu'un sait/voit un meilleur moyen?

+0

Dans cette question, je/nous essayons de faire une version en mémoire/fast /: http://stackoverflow.com/questions/2872249/parallelize-or-vectorize-all-against-all-operation-on-a-large-number-of-matrices –

+0

C'est une mauvaise pratique d'utiliser 'EVAL Pour créer des variables avec des noms générés dynamiquement, utilisez à la place 'STRUCT' avec des références de champs dynamiques: http://matlabwiki.mathworks.com/MATLAB_FAQ#How_can_I_create_variables_A1.2C_A2.2C....2CA10_in_a_loop.3F – Amro

Répondre

1

Voici une version qui allie rapidité et utilisation minimale de la mémoire.

J'utilise fwrite/fread afin que vous pouvez toujours utiliser parfor (et cette fois, je me suis assuré qu'il fonctionne :))

%# assume data is loaded an k is known 

%# find the index pairs for comparisons. This could be done more elegantly, I guess. 
%# I'm constructing a lower triangular array, i.e. an array that has ones wherever 
%# we want to compare i (row) and j (col). Then I use find to get i and j 
[iIdx,jIdx] = find(tril(ones(k,k),-1)); 

%# create a directory to store the comparisons 
mkdir('H_matrix_elements') 
savePath = fullfile(pwd,'H_matrix_elements'); 

%# loop through all comparisons in parallel. This way there may be a bit more overhead from 
%# the individual function calls. However, parfor is most efficient if there are 
%# a lot of relatively similarly fast iterations. 
parfor ct = 1:length(iIdx) 

    %# make the comparison - do double b/c there shouldn't be a memory issue 
    currentComparison = compare(data{iIdx(ct)},data{jIdx{ct}); 

    %# create save-name as H_i_j, e.g. H_104_23 
    saveName = fullfile(savePath,sprintf('H_%i_%i',iIdx(ct),jIdx(ct))); 

    %# save. Since 'save' is not allowed, use fwrite to write the data to disk 
    fid = fopen(saveName,'w'); 

    %# for simplicity: save data as vector, add two elements to the beginning 
    %# to store the size of the array 
    fwrite(fid,[size(currentComparison)';currentComparison(:)]); % ' #SO formatting 

    %# close file 
    fclose(fid) 
end 



%# to read e.g. comparison H_104_23 
fid = fopen(fullfile(savePath,'H_104_23'),'r'); 
tmp = fread(fid); 
fclose(fid); 

%# reshape into 2D array. 
data = reshape(tmp(3:end),tmp(1),tmp(2)); 
+0

Malheureusement,' save() 'ne peut pas être appelé dans un 'parfor'. –

+0

@reve_etrange: Oups. Eh bien, vous devez utiliser par exemple. écrivez, alors. – Jonas

1

Vous pouvez vous débarrasser des appels eval et clear en attribuant le nom de fichier séparément.

for i=1:k 
    [~,m] = size(data{i}); 
    file_name = ['H' int2str(i)];  
    cur_var = cell(1, k-i); 
    for j=i+1:k 
     [~,n] = size(data{j}); 
     cur_var{i,j} = zeros(m, n, 'single'); 
     cur_var{i,j} = compare(data{i}, data{j}); 
    end 
    save(file_name, cur_var); 
end 

Si vous avez besoin des variables enregistrées à prendre des noms différents, utilisez l'option -struct pour enregistrer.

str.(file_name); 
save(file_name, '-struct', str); 
Questions connexes