Utilisant les fonctions de tableau et de tableau dans Mathematica. Ce qui est mieux quand

j'ai été la plupart du temps un utilisateur de fonctions de Table dans mathematica. Cependant, j'ai remarqué que dans plusieurs exemples où j'ai utilisé tableau au lieu de Table pour exprimer le même résultat, il a couru beaucoup plus vite, surtout que la dimension de la table a augmenté.

Donc ma question est la suivante: Lorsque la vitesse d'exécution est la principale préoccupation, quand est-il plus approprié d'utiliser un tableau?

Qu'est-ce qui explique cette différence?

mon avis est que parce que les tableaux supposent une relation fonctionnelle entre les articles dans la liste, il les stocke plus efficacement, donc utilisent moins de mémoire, facilitant ainsi le stockage et le traitement ultérieur?

est-ce que c'est ce qui se passe?

21
demandé sur Brian Tompsett - 汤莱恩 2011-04-23 18:32:45

5 réponses

Array n'a aucun avantage de performance par rapport à Table . Il y a des différences entre eux qui font que l'un est préféré à l'autre.


éditer il a été noté par plusieurs personnes que Table est plus lent sur les tableaux multidimensionnels. Tous ont utilisé la variable pour tenir la taille de la table. Table possède les attributs HoldAll et n'évalue que la limite de l'interation la plus externe. Parce que les itérateurs internes restent non évalué, l'élément du tableau ne se compile pas. En utilisant des nombres explicites ou With avec le résultat de l'auto-compilation:
In[2]:= With[{b = 10^4, c = 10^4},
 {Timing@(#[[1, 1]] &[ar = Array[(# + #2) &, {b, c}]]) , 
  Timing@(#[[1, 1]] &[ta = Table[(i + j), {i, b}, {j, c}]])}
 ]

Out[2]= {{4.93, 2}, {4.742, 2}}

In[3]:= Attributes[Table]

Out[3]= {HoldAll, Protected}


Le Array vous permet de construire un tableau de valeurs de la fonction, tout autant que le Table . Ils prennent des arguments différents. Array prend une fonction:
In[34]:= Array[Function[{i, j}, a[i, j]], {3, 3}]

Out[34]= {{a[1, 1], a[1, 2], a[1, 3]}, {a[2, 1], a[2, 2], 
  a[2, 3]}, {a[3, 1], a[3, 2], a[3, 3]}}

tandis que le tableau prend une forme explicite:

In[35]:= Table[a[i, j], {i, 3}, {j, 3}]

Out[35]= {{a[1, 1], a[1, 2], a[1, 3]}, {a[2, 1], a[2, 2], 
  a[2, 3]}, {a[3, 1], a[3, 2], a[3, 3]}}

Array peut ne passez que sur les tableaux réguliers, alors que Table peut faire une itération arbitraire sur la liste:

In[36]:= Table[a[i, j], {i, {2, 3, 5, 7, 11}}, {j, {13, 17, 19}}]

Out[36]= {{a[2, 13], a[2, 17], a[2, 19]}, {a[3, 13], a[3, 17], 
  a[3, 19]}, {a[5, 13], a[5, 17], a[5, 19]}, {a[7, 13], a[7, 17], 
  a[7, 19]}, {a[11, 13], a[11, 17], a[11, 19]}}

parfois Array peut être plus succinct. Comparer la table de multiplication:

In[37]:= Array[Times, {5, 5}]

Out[37]= {{1, 2, 3, 4, 5}, {2, 4, 6, 8, 10}, {3, 6, 9, 12, 15}, {4, 8,
   12, 16, 20}, {5, 10, 15, 20, 25}}

versus

In[38]:= Table[i j, {i, 5}, {j, 5}]

Out[38]= {{1, 2, 3, 4, 5}, {2, 4, 6, 8, 10}, {3, 6, 9, 12, 15}, {4, 8,
   12, 16, 20}, {5, 10, 15, 20, 25}}

Array permet de construire une expression avec n'importe quelle tête, pas seulement la liste:

In[39]:= Array[a, {3, 3}, {1, 1}, h]

Out[39]= h[h[a[1, 1], a[1, 2], a[1, 3]], h[a[2, 1], a[2, 2], a[2, 3]],
  h[a[3, 1], a[3, 2], a[3, 3]]]

par défaut la tête h est choisie pour être List résultant dans la création du réseau régulier. Le tableau n'a pas cette souplesse.

11
répondu Sasha 2011-04-25 14:48:58

Michael Trott dans Programming (pp 707 - 710) abordent la question des différences entre Array et Table et fait valoir que comme Table a l'attribut HoldAll il calcule son argument pour chaque appel, tandis que Array " dans la mesure du possible " calcule son argument seulement au début. Cela peut entraîner des différences de comportement et de vitesse.

Attributes[Table]

{HoldAll, Protégé}

Attributes[Array]

{protégé}

Michael Trott utilise les exemples suivants pour illustrer la différence de vitesse et de comportement. Je prends le mot à mot de son livre (disque). J'espère ne pas enfreindre les règles en le faisant.

Remove[a, i, j];
a = 0;
Table[a = a + 1; ToExpression[StringJoin["a" <> ToString[a]]][i, j],
       {i, 3}, {j, 3}]

{{a1[1, 1], a2[1, 2], a3[1, 3]}, {a4[2, 1], a5[2, 2], a6[2, 3]}, {a7[3, 1], a8[3, 2], a9 [3, 3]}

a = 0;
Array[a = a + 1; 
 ToExpression[StringJoin["a" <> ToString[a]]], {3, 3}] 

{{a1[1, 1], a1[1, 2], a1[1, 3]}, {a1[2, 1], a1[2, 2], a1 [2, 3]}, {a1[3, 1], a1[3, 2], a1[3, 3]}

(noter la différence de comportement)

pour illustrer l'effet de précomputer le premier argument, il utilise l'exemple suivant (encore une fois mot à mot, p 709).

o[a = 0;
  Table[a = a + 1; 
   ToExpression[StringJoin["a" <> ToString[a]]][i, j],
         {i, 3}, {j, 3}], {2000}] // Timing
Do[a = 0;
  Array[a = a + 1; ToExpression[ StringJoin["a" <> ToString[a]]], 
                                            {3, 3}], {2000}] // Timing

{0.700173, Null}

{0.102587, Null}

(j'utilise mma7 sur Mac. Ma copie de programmation utilisations v5.1. Il pourrait bien y avoir une mise à jour)

ce n'est pas la seule différence entre Array et Table discuté dans programmation , bien sûr.

j'ai vu d'autres réponses, je serai intéressé de savoir ce que pensent les autres de ce point.

9
répondu tomd 2011-04-24 05:51:04

une des raisons pour lesquelles Array peut être plus rapide est qu'il compile souvent mieux son premier argument.

In Mathematica 7:

In[1]:= SystemOptions[CompileOptions -> ArrayCompileLength]

Out[1]= {"CompileOptions" -> {"ArrayCompileLength" -> 250}}

et

In[2]:= SystemOptions[CompileOptions -> TableCompileLength]

Out[2]= {"CompileOptions" -> {"TableCompileLength" -> 250}}

pour que l'on puisse déduire que Array et Table devraient être compilés au même point.

mais essayons. Je vais faire usage de Timo timeAvg fonction :

n = 15;
Array[Mod[#^2, 5]*(1 + #2) &, {n, n}] // timeAvg
Table[Mod[i^2, 5]*(1 + j), {i, n}, {j, n}] // timeAvg

(* Out = 0.00034496 *)

(* Out = 0.00030016 *)

n = 16;
Array[Mod[#^2, 5]*(1 + #2) &, {n, n}] // timeAvg
Table[Mod[i^2, 5]*(1 + j), {i, n}, {j, n}] // timeAvg

(* Out = 0.000060032 *)

(* Out = 0.0005008   *)

ce que nous voyons est que le tableau est capable de compiler Mod[#^2, 5]*(1 + #2) & tandis que Table n'est pas capable de compiler Mod[i^2, 5]*(1 + j) et donc pour Array devient plus rapide lorsque le CompileLength est atteint. Beaucoup de fonctions ne sont pas si favorables. Si vous changez simplement la multiplication en division dans la fonction, ce qui donne un résultat rationnel plutôt qu'entier, alors cette auto-compilation n'arrive pas, et Table est plus rapide:

n = 15;
Array[Mod[#^2, 5]/(1 + #2) &, {n, n}] // timeAvg
Table[Mod[i^2, 5]/(1 + j), {i, n}, {j, n}] // timeAvg

(* Out = 0.000576   *)

(* Out = 0.00042496 *)

n = 16;
Array[Mod[#^2, 5]/(1 + #2) &, {n, n}] // timeAvg
Table[Mod[i^2, 5]/(1 + j), {i, n}, {j, n}] // timeAvg

(* Out = 0.0005744  *)

(* Out = 0.0004352  *)

mais que faire si nous pouvons faire de cette compilation? Si nous utilisons des nombres à virgule flottante, en commençant par 1. , nous obtenons la sortie Real , qui peut être compilée:

n = 15;
Array[Mod[#^2, 5]/(1 + #2) &, {n, n}, 1.] // timeAvg
Table[Mod[i^2, 5]/(1 + j), {i, 1., n}, {j, 1., n}] // timeAvg

(* Out = 0.0006256  *)

(* Out = 0.00047488 *)

n = 16;
Array[Mod[#^2, 5]/(1 + #2) &, {n, n}, 1.] // timeAvg
Table[Mod[i^2, 5]/(1 + j), {i, 1., n}, {j, 1., n}] // timeAvg

(* Out = 0.00010528 *)

(* Out = 0.00053472 *)

et encore une fois, Array est plus rapide sur le plus grand tableau de dimensions.

6
répondu Mr.Wizard 2017-05-23 12:13:57

votre déclaration:

cependant, j'ai remarqué que dans plusieurs exemples où J'ai utilisé Array au lieu de Table pour exprimer le même résultat, il a couru beaucoup plus vite, surtout que la dimension de la table a augmenté.

n'est généralement pas vrai pour les matrices unidimensionnelles . Regardez:

Cl;
Needs["PlotLegends`"]
$HistoryLength = 0;
a = 10^8;
arr = {}; tab = {};
Do[(
   arr = {First@Timing@Array[# &, a], arr};
   tab = {First@Timing@Table[i, {i, a}], tab};
   ), {10}];

ListLinePlot[{Flatten@arr, Flatten@tab}, 
 AxesLabel -> {Style["Iteration", 14], Style["Time", 14]}, 
 PlotLegend -> {Style["Array", 14], Style["Table", 14]}, 
 PlotRange -> {{0, 10}, {1.6, 2}}]  

enter image description here

4
répondu Dr. belisarius 2011-04-23 17:46:07

sans donner quelques exemples concrets, il est difficile de répondre correctement à votre question.

comme Mathematica est un programme source fermé, les implémentations exactes de Table et Array ne peuvent pas être connues, à moins qu'elles ne soient expliquées par des personnes qui ont été impliquées dans le développement de Mathematica.

ces facteurs entravent votre capacité à raisonner quelle structure vous devez utiliser dans quelles circonstances. L'expérimentation sera votre meilleur bet, donc je vous suggère de garder des versions parallèles de vos programmes, l'Une utilisant Table , l'autre utilisant Array . De cette façon, vous pourrez voir lequel est le plus rapide.

Encore mieux, vous pouvez écrire une fonction wrapper qui dépend d'une variable globale. Cette fonction sera, selon la variable, utiliser Table , ou Array comme l'implémentation sous-jacente, de sorte que vous serez en mesure de passer rapidement d'une version à l'autre, sans faire beaucoup modifications à votre code.

1
répondu darioo 2011-04-23 14:41:50