8
votes

Tableaux de passage, sans frais généraux (de préférence "par référence"), pour éviter des blocages de code complexes complexes, dans Matlab?

J'ai des blocs de code complexes, dans un script MATLAB, qui agissent sur de grandes matrices non clairsemées. Le code effectue de nombreuses opérations d'écriture sur des éléments aléatoires dans les tableaux, ainsi que des opérations de lecture. Le code identique doit s'exécuter contre différents (grands) tableaux (c'est-à-dire les mêmes blocs de code, à l'exception des différents noms variables de tableau).

Je ne veux pas avoir de longs blocs de code dupliqué qui diffèrent uniquement dans les noms de matrices.

Malheureusement, lorsque je crée une fonction pour effectuer les opérations, de sorte que le bloc de code n'apparaisse qu'une seule fois, la performance ralentit d'un facteur de 10 ou plus (probablement en raison de la copie du tableau). Cependant, je n'ai pas besoin de la matrice copiée. Je préférerais "réussir par référence", de sorte que le but de l'appel de la fonction est seulement pour éviter d'avoir des blocs de code dupliqué. Il semble y avoir aucun moyen d'éviter la sémantique de la copie-on-écriture, cependant.

Aussi, il est impossible (autant que je comprends) de créer un script (pas une fonction) pour y parvenir, car le script doit contenir des noms de variable identiques en tant que script appelant, donc j'aurais besoin d'un script différent pour chaque Array sur lequel je souhaite exécuter le script, qui gagne rien (je aurais toujours des blocs de code dupliqué).

J'ai examiné la création d'un nom de variable d'alias pour "substitut" pour le nom de la variable de matrice d'intérêt, auquel cas je pourrais appeler un script et éviter le code dupliqué. Cependant, je ne trouve aucun moyen de créer un alias dans Matlab.

Enfin, j'ai essayé d'écrire une fonction qui utilise la fonction evalin () et en passant le nom string nom de la variable de matrice à cette fonction, mais bien que cela fonctionne bien. La performance est également considérablement plus lente - à peu près la même chose que de transmettre les tableaux par valeur à une fonction (au moins une décomposition 10 fois en performance).

Je suis arrivé à la conclusion qu'il est impossible dans MATLAB d'éviter de faire dupliquer les blocs de code lors de la réalisation d'opérations complexes sur des tableaux non clairsemés, dans l'effort visant à éviter les frais généraux horribles que Matlab semble présenter en utilisant toute technique possible d'éviter la dupliquée. Blocs de code.

Je trouve cela difficile à croire, mais je ne peux pas trouver un moyen de le faire.

Quelqu'un peut-il savoir comment éviter les blocs de code dupliqué lors de l'exécution d'opérations complexes identiques sur plusieurs tableaux non clairsemés dans MATLAB?


5 commentaires

Cette réponse pourrait aider. MATLAB utilise la sémantique "Copier sur écriture", de sorte que les matrices sont en fait adoptées "par référence" aux fonctions. J'ai bien peur de ne pas savoir pourquoi vous rencontrez une telle chute dramatique de la performance. Votre fonction change-t-elle des valeurs dans les matrices d'entrée?


Comme je l'ai noté, j'effectue de nombreuses opérations d'écriture à des éléments aléatoires dans les tableaux. Je comprends que c'est pourquoi Matlab est, malheureusement, déclenchant "copie sur l'écriture" de manière étendue dans mon cas. La raison de la chute spectaculaire de la performance semble claire: de grandes matrices non clairsemées sont fréquemment (et inutilement) copiées. Les copies sont inutiles, car je veux que les écritures agissent sur les tableaux original . Cependant, comme indiqué, je ne peux trouver aucun moyen de "réussir par référence" même dans le cas de la sémantique d'écriture (c'est-à-dire que je fais pas veulent "copier sur écriture" Sémantique ).


Je suis en effet, en effet, les variables d'entrée et de sortie le même nom. Êtes-vous absolument certain que cela empêche complètement la sémantique de copie-écriture? Je vois une diminution énorme de la performance pour code identique (pas une ligne unique modifiée), juste en enveloppant le code dans un appel de la fonction (et étant certain d'utiliser les mêmes noms de variables dans la fonction pour le variables d'entrée et de sortie).


La "classe de la poignée" mentionnée dans la réponse que j'ai liée ci-dessus (ou peut-être une classe en général) est probablement ce dont vous avez besoin. Essayez: mathworks.com.au/help/matlab/ref/handle. HTML


@Brianl - fabuleux - les poignées semblent la voie à suivre. Je vais comprendre la syntaxe. Cependant, si vous avez la syntaxe vers le bas et que vous avez envie de poster une brève réponse qui crée simplement un tableau, puis crée une poignée contenant (ou faisant référence à) que la matrice, qui serait utile.


5 Réponses :


1
votes

Selon vos besoins, vous pouvez y accomplir en faisant un fonction imbriquée . xxx

ici, les fonctions partagent le même espace de travail, en particulier la matrice A Aucune variables n'est jamais copiée. Je trouve que c'est un moyen pratique d'organiser le code, en particulier lorsque j'ai beaucoup d'opérations mineures (mais éventuellement verbose) dans le cadre d'un flux de travail plus grand.


3 commentaires

Toutefois, les fonctions imbriquées doivent utiliser le nom même nom de variable comme fonction définie dans la fonction d'appel. Est-il possible d'utiliser des fonctions imbriquées où différentes variables sont agi sur (en mode identique) dans la fonction imbriquée - c'est-à-dire comme si ces variables ont été transmises comme des arguments à l'imbriquage fonction?


Je ne peux pas penser à un moyen de le faire au sommet de ma tête. Si c'est un objectif principal, vous devrez alors aller avec la suggestion de la poignée de @ Brian.


Malheureusement, la solution de Brianl ne fonctionne pas. L'utilisation de poignées donne le résultat correct, mais présente la même diminution drastique de la performance.



4
votes

Vous pouvez essayer de mettre tous vos tableaux dans une matrice de cellule unique et d'utiliser l'index dessus, au lieu de faire référence à des noms. La fonction copiera toujours les tableaux, mais le script peut faire le travail.


2 commentaires

C'est une bonne idée, mais malheureusement, bien que cela donne le résultat correct, cela n'empêche pas la décomposition de la performance. Notez que j'ai utilisé un script , pas une fonction, qui contient le code d'intérêt; Comme vous le suggérez, j'ai défini un paramètre d'index sur l'indice de cellule souhaité contenant mon tableau, et j'appelle simplement le script sur et plus (mais ne copiez pas de tableaux différents dans la cellule; j'accumule simplement les tableaux dans les différentes cellules, puis écrivez valeurs dans ces tableaux).


Malheureusement, il semble en effet que MATLAB peut être fondamentalement incapable d'autoriser les opérations sur les tableaux sans duplication amateur et dangereuse des blocs de code. C'est triste.



2
votes

Une autre réponse:

Il y a un bon article Placez les opérations sur les données . Apparemment, il peut y avoir deux pièges:

  1. (c'est trivial et vous l'avez probablement fait), vous devez utiliser le même nom de variable d'entrée et de sortie non seulement dans la définition de la fonction, mais également où vous l'appelez.
  2. Cela ne fonctionne que si vous appelez votre fonction à partir d'une autre fonction, pas d'une ligne de commande. Weird ... J'ai essayé et, bien qu'il y ait une surcharge, il est très petit (pour les tableaux 10000-by-10000, il était 1 s à partir d'une ligne de commande et 0,000361 s à partir d'une autre fonction).

    Si cela ne fonctionne pas pour vous, vous pouvez utiliser une fonctionnalité non documentée qui vous permet de faire une opération en place dans le fichier C ++ Mex. C'est méchant, mais voici un article à peu près à ce sujet: MATLAB MEX en place Édition


0 commentaires

2
votes

La solution de la poignée suggérée par Brian L fonctionne bien que le premier appel qui modifie les données enveloppées prend beaucoup de temps (car il doit effectuer une copie des données d'origine).

Essayez ceci: P>

somedata.m p> xxx pré>

largeop.m p> xxx pré>

script à tester les performances p>

Elapsed time is 0.364589 seconds.
Elapsed time is 0.450668 seconds.
Elapsed time is 0.001073 seconds.
Elapsed time is 0.443150 seconds.


0 commentaires

9
votes

Comme indiqué par Loren sur son blog , MATLAB prend en charge les opérations fortes> en ligne sur les matrices, ce qui couvre essentiellement les réseaux de passage par référence, les modifier dans une fonction et renvoyer le résultat. Vous semblez savoir que, mais vous indiquez à tort que parce que le script doit contenir des noms de variable identiques en tant que script appelant em>. Voici l'exemple de code qui montre que c'est faux. Lorsque vous testez, veuillez le copier verbatim et enregistrer en tant que fonction:

function inplace_test
y = zeros(1,1e8);
x = zeros(1,1e8);

tic; x = compute(x); toc
tic; y = compute(y); toc
tic; x = computeIP(x); toc
tic; y = computeIP(y); toc
tic; x = x+1; toc

    function x=computeIP(x)
        x = x+1;
    end

    function y=compute(x)
        y = x+1;
    end
end

Elapsed time is 0.247798 seconds.
Elapsed time is 0.257521 seconds.
Elapsed time is 0.229774 seconds.
Elapsed time is 0.237215 seconds.
Elapsed time is 0.090446 seconds.


0 commentaires