2017-06-25 4 views
1

Der folgende Code funktioniert, aber wenn ich for in parfor zu ändern, gab es einen Fehlerparfor Fehler "Index Matrix Dimensionen übersteigt"

Index exceeds matrix dimensions 

Dies ist mein Code

a=zeros(3,1); 
for t=1:2 
    ind=randsample(3,2) 
    a=pf(a,ind) 
end 

function a=pf(a,ind) 
a(ind)=a(ind)+2; 
end 

Wie kann ich Dieser Code funktioniert ohne den Fehler?

+0

Was erwarten Sie von der "Parfor" mit Ihrer Schleife? Und bitte antworten Sie nicht "beschleunigen". –

+0

Hallo, das ist der vereinfachte Code. Der echte Code hat eine große Matrix und ich möchte parfor verwenden, um ihn zu beschleunigen. –

+0

OK, ich habe überprüft und ich kann Ihren Fehler reproduzieren (löschte meinen vorherigen Kommentar). Das Problem ist wahrscheinlich, dass die Parfor in diesem Zusammenhang bedeutungslos ist. Verstehst du, was Parfor tut? –

Antwort

2

Sie sehen den Fehler, weil Sie parfor in Ihrem Code missbrauchen. Sie haben die relevante Dokumentation nicht genug gelesen, und Sie scheinen zu glauben, dass parfor magischer Feenstaub ist, der Ihre Berechnung schneller macht, unabhängig von der Berechnung. Nun, ich habe schlechte Nachrichten.

Werfen wir einen genaueren Blick auf Ihr Beispiel nehmen:

a = zeros(3,1); 
% usual for 
disp('before for') 
for t=1:2 
    ind = randsample(3,2); 
    a = pf(a,ind); 
    disp(a); % add printing line 
end 

% parfor 
disp('before parfor') 
parfor t=1:2 
    ind = randsample(3,2); 
    a = pf(a,ind); 
    disp(a); % add printing line 
end 

Der Ausgang:

before for 
    2 
    2 
    0 

    2 
    4 
    2 

before parfor 
Error: The variable a is perhaps intended as a reduction variable, but is actually an uninitialized temporary. 
See Parallel for Loops in MATLAB, "Temporary Variables Intended as Reduction Variables". 

Wie Sie, im letzteren Fall sehen können, gibt es keine Abzüge innerhalb des parfor, so es doesn Ich werde nicht einmal weglaufen. Siehe auch die Warnung über den Typ der Variablen. Die Variable a wird von der Ausführungs-Engine falsch erkannt, weil das, was Sie damit machen, keinen Sinn ergibt.

Was also zu tun? Sie müssen Ihr Problem so formulieren, dass es mit parfor kompatibel ist. Dies hängt leider davon ab, was genau Sie mit Ihrer Matrix machen. Für Ihren speziellen Fall von Zufallselementen erhöht wird, schlage ich vor, dass Sie die einzelnen Schritte separat in der Schleife zu sammeln, und summieren sie danach auf:

a = zeros(3,1); % only needed for size; assumed that it exists already 
numiters = 2; 
increments = zeros([size(a), numiters]); % compatible with a proper 2d array too 
parfor t=1:numiters 
    ind = randsample(3,2); 
    % create an auxiliary increment array so that we can use a full slice of 'increments' 
    new_contrib = zeros(size(a)); 
    new_contrib(ind) = 2; 
    increments(:,t) = new_contrib; 
    disp(increments(:,t)); % add printing line 
end 

% collect increments along last axis 
a = sum(increments,ndims(increments)); 
disp(a) 

Ausgang:

 2 
    0 
    2 

    2 
    2 
    0 


    4 
    2 
    2 

Hinweis das Fehlen von Warnungen und der Vorhandensein einer sinnvollen Antwort. Refactoring der Schleife auf diese Weise transparently signalisiert MATLAB was die Variablen tun, und dass increments wird durch unabhängige Iterationen der parfor Schleife gefüllt. Diese ist die Art und Weise, in der parfor "Berechnungen beschleunigen" kann, eine sehr spezifische und kontrollierte Art, die Einschränkungen in der Logistik innerhalb der Schleife impliziert.

+1

Vielen Dank für Ihre Hilfe. Sehr nützlich. Ich habe Ihren Code etwas vereinfacht. Anstatt 'increments' zu verwenden, füge ich 'new_contrib' direkt zu 'a' in jeder Schleife hinzu: a = a + new_contrib. Ich muss das tun, weil es eine große Matrix im echten Code ist. –

+0

@ChuchuXiang Ich erwarte nicht, dass das funktioniert, aber wenn es so ist, dann ist alles gut. Danke für die Rückmeldung. –

+1

Ich habe das versucht. Es funktioniert und gab die gleiche Antwort. Sie müssen nur 'new_contrib = Nullen (Größe (a))' in konstante Größe ändern: 'new_contrib = Nullen (3,1)'. Normalerweise müssen die Schleifeniterationen in 'parfor' unabhängig sein, aber die einzige Ausnahme ist die Reduktion (akkumuliert einen Wert). Vielen Dank –

1
n = 2; 
a=zeros(3,1); 
ind=zeros(3,2,n); 
for ii = 1:n 
    ind(:,:,ii) = randsample(3,2); 
end 

for t=1:n 
    a=pf(a,ind(:,:,t)); 
end 

function a=pf(a,ind) 
    a(ind)=a(ind)+2; 
end 

Die oben bekommt die randsample aus der Schleife, die hier wahrscheinlich das Problem. Beachten Sie, dass randsample direkte 3D-Matrix-Erstellung nicht unterstützt, also habe ich das in einer Schleife initialisiert.

Verwandte Themen