6 votes

Sur PackedArray, chercher des conseils pour les utiliser

Je n'ai jamais utilisé PackedArray auparavant, mais j'ai commencé à les utiliser après avoir lu une discussion à ce sujet ici aujourd'hui.

J'ai beaucoup de matrices de grande taille en 1D et 2D de réels seulement, sans symboles (c'est un solveur d'équations aux différences finies), et j'ai donc pensé que je devrais profiter de l'utilisation de PackedArray.

J'ai une fonction d'initialisation où j'alloue toutes les données/grilles nécessaires. J'ai donc utilisé ToPackedArray sur elles. Cela semble un peu plus rapide, mais je dois faire plus de tests de performance pour mieux comparer la vitesse avant et après et aussi comparer l'utilisation de la RAM.

Mais pendant que je regardais cela, j'ai remarqué que certaines opérations en M renvoient automatiquement des listes en PackedArray, et d'autres non.

Par exemple, cela ne renvoie pas de packed array

a = Table[RandomReal[], {5}, {5}];
Developer`PackedArrayQ[a]

Mais cela le fait

a = RandomReal[1, {5, 5}];
Developer`PackedArrayQ[a]

et cela le fait aussi

a = Table[0, {5}, {5}];
b = ListConvolve[ {{0, 1, 0}, {1, 4, 1}, {0, 1, 1}}, a, 1];
Developer`PackedArrayQ[b]

et la multiplication de matrices renvoie le résultat en packed array

a = Table[0, {5}, {5}];
b = a.a;
Developer`PackedArrayQ[b]

Mais la multiplication élément par élément ne le fait pas

b = a*a;
Developer`PackedArrayQ[b]

Ma question : Y a-t-il une liste quelque part qui documente quelles commandes M renvoient PackedArray vs. pas? (en supposant que les données répondent aux exigences, telles que Real, pas de mélange, pas de symboles, etc..)

Aussi, une question mineure, pensez-vous qu'il serait mieux de vérifier d'abord si une liste/matrice créée est déjà packée avant d'appeler ToPackedArray dessus? Je pense que l'appeler ToPackedArray sur une liste déjà packée ne coûtera rien, car l'appel se terminera immédiatement.

merci,

mise à jour (1)

Je voulais juste mentionner que j'ai découvert que les symboles PackedArray ne sont pas autorisés dans une démo CDF car j'ai eu une erreur en en téléchargeant une avec un tel symbole. J'ai donc dû supprimer tout mon code de pack. Comme j'écris principalement des démos, ce sujet est maintenant juste d'un intérêt académique pour moi. Mais je voulais remercier tout le monde pour le temps et les bonnes réponses.

9voto

Brett Champion Points 7740

Il n'existe pas de liste exhaustive. Pour souligner quelques points :

  • Les opérations de base avec des tableaux compactés auront tendance à rester compacts :

    In\[66\]:= a = RandomReal\[1, {5, 5}\];
    
    In\[67\]:= Developer\`PackedArrayQ /@ {a, a.a, a\*a}
    
    Out\[67\]= {True, True, True}
  • Notez ci-dessus que ma version (8.0.4) ne décompacte pas pour une multiplication élément par élément.

  • Savoir si un Table donnera un tableau compacté dépend du nombre d'éléments :

    In\[71\]:= Developer\`PackedArrayQ\[Table\[RandomReal\[\], {24}, {10}\]\]
    
    Out\[71\]= False
    
    In\[72\]:= Developer\`PackedArrayQ\[Table\[RandomReal\[\], {24}, {11}\]\]
    
    Out\[72\]= True
    
    In\[73\]:= Developer\`PackedArrayQ\[Table\[RandomReal\[\], {25}, {10}\]\]
    
    Out\[73\]= True
  • On["Packing"] affichera des messages pour indiquer quand les choses sont décompactées :

    In\[77\]:= On\["Packing"\]
    
    In\[78\]:= a = RandomReal\[1, 10\];
    
    In\[79\]:= Developer\`PackedArrayQ\[a\]
    
    Out\[79\]= True
    
    In\[80\]:= a\[\[1\]\] = 0 (\* forcer la décompilation en raison d'un type incompatible \*)
    
       Developer\`FromPackedArray::punpack1: Décompactage du tableau avec des dimensions {10}. >>
    
    Out\[80\]= 0
  • Les opérations qui effectuent une inspection par élément décompactent généralement le tableau,

    In\[81\]:= a = RandomReal\[1, 10\];
    
    In\[82\]:= Position\[a, Max\[a\]\]
    
       Developer\`FromPackedArray::unpack: Décompactage du tableau dans l'appel à Position. >>
    
    Out\[82\]= {{4}}
  • La pénalité de l'appel de ToPackedArray sur une liste déjà compactée est suffisamment faible pour ne pas trop s'en soucier :

    In\[90\]:= a = RandomReal\[1, 10^7\];
    
    In\[91\]:= Timing\[Do\[Identity\[a\], {10^5}\];\]
    
    Out\[91\]= {0.028089, Null}
    
    In\[92\]:= Timing\[Do\[Developer\`ToPackedArray\[a\], {10^5}\];\]
    
    Out\[92\]= {0.043788, Null}
  • L'interface préfère les tableaux compacts aux décompilés, ce qui peut se manifester lors de l'utilisation de Dynamic et Manipulate :

    In\[97\]:= Developer\`PackedArrayQ\[{1}\]
    
    Out\[97\]= False
    
    In\[98\]:= Dynamic\[Developer\`PackedArrayQ\[{1}\]\]
    
    Out\[98\]= True
  • Lorsque vous analysez les performances, concentrez-vous sur les cas où de grandes listes sont décompactées, plutôt que les petites. Sauf si les petites sont dans de grandes boucles.

7voto

Mike Honeychurch Points 1473

Ceci est simplement un addendum à la réponse de Brett:

SystemOptions["CompileOptions"]

vous donnera les longueurs utilisées pour lesquelles une fonction renverra un tableau compressé. Donc, si vous deviez compresser une petite liste, en alternative à l'utilisation de Developer`ToPackedArray, vous pourriez temporairement définir un nombre plus petit pour l'une des options de compilation. par exemple

SetSystemOptions["CompileOptions" -> {"TableCompileLength" -> 20}]

Notez également certaines différences entre les fonctions qui, pour moi au moins, ne semblent pas intuitives, donc je dois généralement tester ce genre de choses chaque fois que je les utilise plutôt que de savoir instinctivement ce qui fonctionnera le mieux :

f = # + 1 &;
g[x_] := x + 1;
data = RandomReal[1, 10^6];

On["Packing"]
Timing[Developer`PackedArrayQ[f /@ data]]
{0.131565, True}

Timing[Developer`PackedArrayQ[g /@ data]]
Developer`FromPackedArray::punpack1: Dépaquetage du tableau avec les dimensions {1000000}.
{1.95083, False}

4voto

Autre ajout à la réponse de Brett : Si une liste est un tableau compacté, alors un ToPackedArray est très rapide car cela est vérifié très tôt. Vous pourriez aussi trouver ceci utile :

http://library.wolfram.com/infocenter/Articles/3141/

En général, pour les questions numériques, regardez les discussions de Rob Knapp et/ou Mark Sofroniou.

Lorsque je développe des codes numériques, j'écris la fonction puis j'utilise On["Packing"] pour m'assurer que tout est compacté comme il se doit.

Concernant la réponse de Mike, le seuil a été introduit car pour de petites choses il y a des frais généraux. Où se situe le seuil dépend du matériel. Il pourrait être judicieux d'écrire une fonction qui définit ces seuils en fonction des mesures effectuées sur l'ordinateur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X