Übergeben von Arrays ohne Overhead (vorzugsweise "per Referenz"), um das Duplizieren komplexer Code-Blöcke in Matlab zu vermeiden?

8

Ich habe komplexe Codeblöcke in einem Matlab-Skript, die auf große, nicht-spärliche Arrays wirken. Der Code führt viele Schreiboperationen für zufällige Elemente in den Arrays sowie Leseoperationen aus. Der identische Code muss gegen verschiedene (große) Arrays ausgeführt werden (d. H. Die gleichen Codeblöcke, außer für verschiedene Array-Variablennamen).

Ich möchte keine langen, duplizierten Codeblöcke haben, die sich nur in den Array-Namen unterscheiden.

Wenn ich eine Funktion zum Ausführen der Operationen erstelle, sodass der Codeblock nur einmal erscheint, wird die Performance leider um den Faktor 10 oder mehr verlangsamt (vermutlich aufgrund des Kopierens des Arrays). Ich brauche das Array jedoch nicht kopiert. Ich würde es vorziehen, "durch Verweis" zu übergeben, so dass der Zweck des Funktionsaufrufs NUR ist, doppelte Codeblöcke zu vermeiden. Es scheint jedoch keine Möglichkeit zu geben, die Copy-on-Write-Semantik zu vermeiden.

Außerdem ist es (soweit ich es verstehe) unmöglich, ein Skript (keine Funktion) zu erstellen, weil das Skript identische Variablennamen wie das aufrufende Skript enthalten muss, also würde ich für jedes ein anderes Skript benötigen Array, auf dem ich das Skript ausführen möchte, das nichts bringt (ich hätte immer noch Code-Blöcke dupliziert).

Ich habe nach einem Namen für eine Alias-Variable gesucht, der den Namen der interessierenden Array-Variablen ersetzen soll. In diesem Fall könnte ich ein Skript aufrufen und doppelten Code vermeiden. Ich finde jedoch keine Möglichkeit, in Matlab einen Alias ​​zu erstellen.

Schließlich habe ich versucht, eine Funktion zu schreiben, die die Funktion evalin() verwendet und den String Namen der Array-Variablen an diese Funktion weiterleitet, aber obwohl dies funktioniert, ist die Leistung auch wesentlich langsamer - Etwa so, als würde man die Arrays nach Wert an eine Funktion übergeben (mindestens 10 Mal weniger Leistung).

Ich komme zu der Schlussfolgerung, dass es in Matlab unmöglich ist, die Duplizierung von Codeblöcken bei komplexen Operationen auf nicht-spärlichen Arrays zu vermeiden, um den grässlichen Overhead zu vermeiden, den Matlab mit einer möglichen Technik der Vermeidung von Duplikaten zu bieten scheint Codeblöcke.

Ich finde es schwer zu glauben, aber ich kann keinen Weg finden.

Kennt jemand eine Möglichkeit, doppelte Codeblöcke zu vermeiden, wenn identische komplizierte Operationen auf mehreren Nicht-Sparse-Arrays in Matlab durchgeführt werden?

    
Dan Nissenbaum 25.10.2012, 22:32
quelle

5 Antworten

9

Wie von von Loren in seinem Blog erwähnt, MATLAB unterstützt inline Operationen auf Matrizen, die im Wesentlichen das Übergeben von Arrays als Referenz, das Modifizieren von ihnen in einer Funktion und das Zurückgeben des Ergebnisses umfasst. Sie scheinen das zu wissen, aber Sie geben dies fälschlicherweise als an, weil das Skript identische Variablennamen wie das aufrufende Skript enthalten muss . Hier ist ein Codebeispiel, das zeigt, dass dies falsch ist. Bitte kopieren Sie es wörtlich und speichern Sie es als Funktion:

%Vor%

Zeit Ergebnisse auf meinem Computer:

%Vor%

Wie Sie sehen, sind die beiden letzten Aufrufe, die eine direkte -Funktion verwenden, für beide Eingabearrays x und y gleichermaßen schnell. Außerdem sind sie genauso schnell wie x = x+1 ohne eine Funktion auszuführen. Die einzige wichtige Sache ist, dass innerhalb der Funktion Ein- und Ausgabeparameter gleich sind. Und da ist noch etwas ...

Wenn ich rate, was mit Ihrem Code nicht stimmt, würde ich sagen, dass Sie geschachtelte Funktionen erstellt haben, von denen Sie erwarten, dass sie an Ort und Stelle sind. Und sie sind nicht. Der folgende Code funktioniert nicht:

%Vor%

Die untere Zeile - seien Sie vorsichtig mit diesen verschachtelten Funktionen ..

    
angainor 26.10.2012, 06:14
quelle
4

Sie können versuchen, alle Ihre Arrays in ein einzelnes Zellenarray zu setzen und dafür einen Index zu verwenden, anstatt sie nach Namen zu benennen. Die Funktion wird weiterhin die Arrays kopieren, aber das Skript kann die Aufgabe übernehmen.

    
Valery Belayev 25.10.2012 23:42
quelle
2

Die von Brian L vorgeschlagene Handle-Lösung funktioniert, obwohl der erste Aufruf, der die umgebrochenen Daten ändert, sehr lange dauert (weil er eine Kopie der Originaldaten erstellen muss).

Versuchen Sie Folgendes:

SomeData.m

%Vor%

LargeOp.m

%Vor%

Skript zum Testen der Leistung

%Vor%

Ergebnisse

%Vor%     
grantnz 26.10.2012 01:27
quelle
2

Eine andere Antwort:

Es gibt einen guten Artikel In-Place-Operationen für Daten . Anscheinend gibt es zwei Fallstricke:

  1. (das ist trivial und Sie haben es wahrscheinlich getan) Sie sollten den gleichen Variablennamen in und aus verwenden, nicht nur in der Definition der Funktion, sondern auch dort, wo Sie sie nennen.
  2. Dies funktioniert nur, wenn Sie Ihre Funktion von ANDERER FUNKTION aufrufen, nicht von einer Befehlszeile. Seltsam ... Ich habe es versucht, und obwohl es einen Overhead gibt, ist es sehr klein (für 10000 mal 10000 Arrays war es 1 Sekunde von einer Befehlszeile und 0,000361 Sekunden von einer anderen Funktion).

Wenn dies für Sie nicht funktioniert, können Sie eine nicht dokumentierte Funktion verwenden, mit der Sie die In-Place-Operation in der C ++ MEX-Datei ausführen können. Das ist scheußlich, aber hier ist ein Artikel dazu: Matlab Mex-In-Place-Bearbeitung

    
Valery Belayev 26.10.2012 01:08
quelle
1

Je nach Ihren Anforderungen können Sie dies erreichen, indem Sie ein verschachtelte Funktion .

%Vor%

Hier teilen sich die Funktionen den gleichen Arbeitsbereich, insbesondere die A -Matrix, so dass niemals Variablen kopiert werden. Ich finde es eine bequeme Art, Code zu organisieren, besonders wenn ich viele kleinere (aber möglicherweise ausführliche) Operationen als Teil eines größeren Workflows habe.

    
drhagen 25.10.2012 23:14
quelle

Tags und Links