10
votes

Comment accélérer le remplacement de Mathematica des éléments matriciels

J'ai plusieurs matrices 100x15; L'un d'eux est une distance. Lorsque des éléments de cette matrice dépassent une liaison, je souhaite réinitialiser ces éléments à zéro et réinitialiser également les éléments correspondants de trois autres matrices à zéro. Voici ma façon idiote (mais ça marche): xxx

j'ai essayé remplappart : xxx

(quelque chose comme Ceci, je ne l'ai pas pratique; cela a été fait assez correctement pour exécuter), mais c'était aussi lent que la boucle et n'a pas produit la structure de remplacement correcte de la matrice Xnow. Veuillez vous conseiller sur la façon de faire cela de manière raisonnablement rapide, car ce CALC est à l'intérieur d'une autre boucle (au fil du temps) qui s'exécute plusieurs fois. Le calcul général est bien sûr, maintenant, très lent. Merci d'avance.


Voici comment j'ai fait cela dans R; Très simple et rapide: xxx


2 commentaires

Bonjour Bill. Votre question va bien ici. Nous avons également un proposition pour créer un site spécifique à Mathematica. S'il vous plaît envisager de vous engager à cela pour l'emporter sur le terrain.


Pas une réponse complète mais une observation. La lenteur est due à la vérification> et je n'ai pas pu trouver de fonction intégrée qui effectue ce chèque plus rapidement que la vérification du modèle _? (#> L &). Je pense que la majeure partie de l'accélération des solutions suggérées peut être attribuée à des améliorations sur l'utilisation d'une boucle de Sparesarray, mapthread. Les fonctions intégrées pour


6 Réponses :


2
votes

Peut être xxx pré>

maintenant effectuez le remplacement p> xxx pré>

modifier (1) strong> p> p> P>

Voici une vitesse rapide comparant les 4 méthodes ci-dessus, la boucle, puis Brett, moi et Verbeia. Peut-être que quelqu'un puisse les vérifier. J'ai utilisé les mêmes données pour tous. créé des données aléatoires une fois, puis utilisées pour chaque test. Même limite (appelée L) J'ai utilisé la taille de matrice de 2 000 par 2 000 par 2 000. p>

SE SE SE Vitesse Les numéros de synchronisation ci-dessous n'incluent pas l'allocation de données. P>

i Exécutez les tests une fois. P>

C'est ce que je vois: p>

pour 2 000 sur 2 000 matrices: h2>
  1. Bill (boucle): 16 secondes li>
  2. moi ( replacePart code>): 21 secondes li>
  3. Brett ( SPARSARRAY CODE>): 7.27 secondes li>
  4. verbeia ( cartthread code>): 32 secondes li> ol>

    pour 3 000 sur 3 000 matrices: h2>
    1. Bill (boucle): 37 secondes li>
    2. moi ( replactpart code>): 48 secondes li>
    3. Brett ( SPARSARRAY CODE>): 16 secondes LI>
    4. verbeia ( cartthread code>): 79 secondes li> ol>

      Donc, il semble que SPARSARRAY code> est le plus rapide. (Mais s'il vous plaît vérifier pour vous assurer que je n'ai pas cassé quelque chose) p>

      Code ci-dessous: P>

      Génération de données forte> p>

      %test, on same machine, 4GB ram, timing uses cpu timing using tic/toc
      %allocate data
      nRow = 3000;
      nCol = 3000;
      
      %generate a random matrix of real values
      %between 1 and 3
      xnow = 1 + (3-1).*rand(nRow,nRow);
      
      %allocate the other 3 matrices
      a=zeros(nRow,nCol);
      b=a;
      c=b;
      
      %set limit
      limit=2;
      
      %engine
      tstart=tic;
      
      for i=1:nRow
          for j=1:nCol
              if xnow(i,j) > limit
                  xnow(i,j) = 0;
                  a(i,j) = 0;
                  b(i,j) = 0;
                  c(i,j) = 0;
              end
          end
      end
      toc(tstart)
      


1 commentaires

J'ai toujours du mal à trouver les commandes correctes à utiliser. Une fois que j'ai maîtrisé cette partie, je vais ensuite passer à la prochaine phase, qui doit filtrer ceux qui sont lents :)



2
votes

remplapparts est notoirement lent.

cartthread devrait faire ce que vous voulez - notez le troisième argument. xxx

et pour les quatre matrices xxx


6 commentaires

Salut- j'ai essayé cela et ça ne marche pas. J'ai utilisé la variable l où vous avez 0,6 ci-dessus. Cela dépit de quelques erreurs et de moudre pendant une longue période. (Tag heures protégées) .... ???


Oui, il est défini plus tôt dans le cahier. Ai-je besoin à la fois des déclarations de carthread ou du dernier? J'ai essayé les deux manières; Je vais essayer à nouveau.


Juste le dernier. J'ai montré les deux afin que vous puissiez voir ce qui se passait - la programmation fonctionnelle est tout à fait inconnu si vous avez programmé dans d'autres langues.


Oh, je viens de réaliser le problème - la cellule définissant xnow, etc. devrait être dans une cellule distincte de la commande mapthread . J'ai supposé que tu te rendrais compte ça. Si nécessaire, mettez un ; après le bit qui dit aléatoireReal [...] . Mettre chaque instruction dans une cellule distincte et tout ira bien.


Ok, je l'ai essayé exactement comme vous l'avez ici, pas dans mes calculs principaux; Il gère et montre des zéros de manière vraisemblablement là où ils devraient être (> 0,6 valeurs remplacées), mais les matrices elles-mêmes ne sont pas modifiées. "XNOW" avant et après avoir exécuté la carte caratère est inchangée. J'en ai besoin pour avoir les zéros dedans après la carte. ????


Voir la version modifiée. Oui, vous devez réaffecter XNOW etc., à ce cartthread expression. Ce sont les sortes de bases qui seraient révélées dans un tutoriel d'introduction. Désolé, j'avais supposé que vous seriez familier avec l'idée de mission.



2
votes

Cette approche fonctionne-t-elle pour vous?

matrixMask = 
 SparseArray[Thread[Position[xnow, _?(# > 0.75 &)] -> 0.], 
  Dimensions[xnow], 1.]; 
xnow = xnow * matrixMask;
cellactvA = cellactvA * matrixMask;
cellactvB = cellactvB * matrixMask;
cellactvC = cellactvC * matrixMask;


2 commentaires

Merci, oui, cela fonctionne, mais est au moins aussi lent que la boucle d'origine. (Ceci est exécuté environ 2000 fois ....)


@bill, s'il vous plaît voir mon édition (1). Je vois que la méthode Sparsarray est au moins deux fois plus rapide que la méthode de la boucle. Je n'ai essayé que pour 2 000 sur 2 000 matrices. Vous pouvez essayer de plus grandes tailles, le code est ci-dessous.



3
votes

Une autre méthode qui semble être rapide xxx

basée sur des tests limités dans la configuration de Nasser, il semble qu'il est aussi rapide que le masque SPARSARRAY -BASED. < / p>

EDIT: Peut combiner avec SPARSARRAY pour obtenir une légère vitesse xxx

EDIT 2: Inspiré de la solution de Ruebenko, une autre Fonction intégrée (pas aussi vite que UnitStep mais beaucoup plus rapide que les autres): xxx


0 commentaires

11
votes

Que diriez-vous:

mask = UnitStep[limit - xnow];
{xnow*mask, cellactvA2*mask, cellactvB2*mask, cellactvC2*mask}


14 commentaires

Pour obtenir le XOOW MATRIC aussi bien que xnet = $ xnow * matrixmask2


Je pense que tu es le gagnant. Ceci est environ 50 fois plus rapide que la boucle do sur une matrice 1000x1000.


Non, vous devriez aussi tester les autres choses - compilez-le, ou la forme compilée de la boucle de DO fait bien? Comment, utilise N [UNITSSTEP [..]] influence les performances. C'est juste une idée d'une direction.


Je suppose que MMA utilisera une version compilée de UnitStep ici, car les arguments sont numériques.


Excellent! Cela représente plus de 30 fois plus vite que les autres méthodes suggérées sur les matrices 2K et 3K. Emballage avec N [..] ou SPARSARRAY [.] n'aide pas - en réalité, il double presque le temps.


@kguler, merci de vérifier. Avez-vous également essayé les versions compilées?


J'ai vérifié, la compilation n'améliore pas les choses.


Prettout impressionnant - je pensais que ma méthode serait plus rapide car, dans votre méthode, des éléments non affectés doivent être multipliés, mais votre code semble être toujours de 1,5x - 2 fois plus rapidement. +1


Merci, Lénoïde, tu viens de faire mon 1000 ;-)


@Ruebenko félicitations! Je suis très heureux d'être celui de le faire :). Mais, sérieusement, votre code est le meilleur pour ce problème, des solutions postées jusqu'à présent, et j'espère que le nombre de voix final reflétera cela.


Tache la nuit dernière, j'ai pensé à Matrixmask2 = Signe [Clip [Limite - $ xnow, {0, Infinity}]] , mais UnitStep


Je vais avoir crié à ce sujet, mais ... cette solution est sûre, je suis sûr, une réponse très élégante, mais comme je l'ai indiqué dans la question initiale, je suis novice à MMA. (Cette partie a été éditée.) Je n'ai aucune idée de ce que $ xnow $ $ b $ C est ou ce que doit faire. Les réponses ci-dessus semblent visibles dans la Communauté d'experts, oubliant la personne qui a posé la question de la première place. J'ai essayé ce code comme présenté ci-dessus et il a couru pour toujours et je devais l'abandonner. Je reconnais que ce site Web vise davantage à des personnes de niveau supérieur, alors peut-être que je suis au mauvais endroit. Merci à tous pour les efforts, de toute façon.


@bill, je vais éditer mon message plus tard pour refléter vos commentaires. $ signifie rien de spécial, je viens d'utiliser pour pouvoir utiliser les exemples de données ci-dessous. Mais maintenant pour le dîner.


Merci, c'est à peu près ce que j'ai fait: Matrixmask = UnitStep [L - XNOW]; xow = xow matricemask; CellAcTeva = CellAcTeva MATRIXMASK; CellAcoTVB = CellActacTVB Matrixmask; CellAcTVC = CellAcTVC MATRIXMASK; et ça marche. Les calculs sont un peu plus rapides maintenant, mais il s'avère une entreprise de fonctionnement qui prend beaucoup de temps également. Je vais travailler sur cela et peut-être écrire cela, plus tard. Merci a tous pour votre aide.



8
votes

Ce qui suit sera basé sur des pièces de ménage, évitez les trucs superfaus et très vite:

In[78]:= 
Do[
  With[{L = 5},
    With[{flatzpos = getFlatZeroDistancePositions[xnow,L]},
       Map[replaceWithZero[#,flatzpos ]&,{xnow,cellactvA,cellactvB,cellactvC}]]
  ],
  {1000}]//Timing

Out[78]= {0.203,Null}


3 commentaires

Très beau Leonid! La seule chose qui me dérange est que d'écrire une telle solution à Mathematica prend trop de temps (peut-être pas pour vous, mais vous êtes une maîtrise bien sûr). Je pense que Mathematica devrait être aussi rapide que R ou Matlab hors de la boîte, pour les boucles. C'est à dire. Il devrait y avoir des optimisations plus intelligentes dans les coulisses. Parlez à twj ou rg peut-être ...


@Rolf merci! J'ai le même sentiment concernant les boucles. C'est une tâche difficile pour Mathematica en raison de sa nature symbolique cependant. Je suis sûr que cela va éventuellement y arriver. Notez que la solution d'Oliver est toujours plus rapide et plus simple que la mienne (quelque chose que je n'ai pas dépint de ce problème, car je pensais que des multiplications supplémentaires d'éléments non affectés dans sa solution seraient plus coûteuses).


Léonid, je vois que vous utilisez ExtractPositionFromsParsParsarRay plutôt que ["Adjacencylists"] . Habitude ou délibéré?