8
votes

Y a-t-il une opération de produit rapide pour les packedarrays?

dans Mathematica Un vecteur (ou une matrice rectangulaire) contenant toutes les entiers de taille de la machine ou des flotteurs peut être stocké dans un tableau emballé. Ces objets prennent moins de mémoire et certaines opérations sont beaucoup plus rapides sur elles.

aléatoireReal code> produit une matrice emballée lorsque cela est possible. Un tableau emballé peut être déballé avec le développeur code> fonction code> de Packedarray code> p>

Considérez ces horaires P>

lst = RandomReal[100, 5000000];
Times @@ lst // Timing

lst = Developer`FromPackedArray[lst];
Times @@ lst // Timing

Out[1]= {0.875, 5.8324791357*10^7828854}

Out[1]= {0.625, 5.8324791357*10^7828854}


0 commentaires

3 Réponses :


9
votes

Je me suis aussi demandé s'il y avait un équivalent multiplicatif sur total .

a vraiment pas si mauvaise solution est xxx

tant que les chiffres sont positifs et ne sont pas trop gros ou petits, Ensuite, les erreurs d'arrondi ne sont pas trop mauvaises. Une supposition quant à ce qui pourrait se passer pendant l'évaluation est que: (1) à condition que les chiffres soient des flotteurs positifs, l'opération journal peut être rapidement appliquée à la matrice emballée. (2) Les chiffres peuvent ensuite être rapidement ajoutés à l'aide de la méthode de la matrice emballée S. / CODE>. (3) Ensuite, ce n'est que la dernière étape où un flotteur de taille non machine nécessite de se poser.

voir Cela répond donc pour une solution qui fonctionne pour des flotteurs positifs et négatifs.

Vérifiez rapidement que cette solution fonctionne avec des flotteurs qui donnent une réponse de taille non machine. Comparez avec Andrew's (beaucoup plus rapide) compilédlistProduct : xxx

si vous choisissez plus grand (> 1 ) réels, puis < Code> CompiledListProduct donnera l'avertissement Compiledfunction :: CFNE: Erreur numérique rencontrée; En procédant avec une évaluation non pondérée. et prendra du temps pour donner un résultat ...


Un curio est que somme et / code> peut prendre des listes arbitraires. somme fonctionne bien xxx

mais pour long packedarray s, tel que les exemples de test ici, produit < / code> échoue car le code compilé automatiquement (dans la version 8.0) ne capte pas les sousflages / débordements correctement: xxx

Le travail autour fourni par le support technique WRI utile est de tourner hors de la compilation du produit à l'aide de SetSystemOptions ["Compileoptions" -> {"ProduitCompilLength" -> Infinity}] . Une autre option consiste à utiliser lst = développeur`frompackedarray [lst] .


11 commentaires

Votre "très mauvaise solution" peut ne pas avoir de bonne précision, mais est beaucoup plus rapide et peut vraiment être le meilleur possible compte tenu de la nature de la multiplication. Si rien de mieux est posté, cela obtient ma coche. +1 Aussi, sur mon système (Win32, MMA7), il est environ 40 fois plus rapide que fois @@ sur votre exemple.


Bonne idée. Le journal vous permet de conserver presque tous les calculs de la machine de précision de la machine.


@ADEDREW: Si seulement je pouvais prétendre que c'était la raison pour laquelle j'ai utilisé journal ... Quand j'ai fourni la réponse ma motivation originale était juste pour transformer le produit en une somme, je n'avais même pas pensé à Machine vs arithmétique de précision arbitraire.


PRODTOTAL [] est prévu d'apparaître dans la version 8.π


@Belisarius 8.π? Si c'est l'humour de mathématicien, c'est sur ma tête.


@Monsieur. Ohh Eh bien, mon sens de l'humour est asymptotiquement à l'approche de l'idiocy au fil des ans.


@belisarius, non, que était drôle. :-RÉ


+1, transformant la multiplication en addition. Simple et efficace.


Au fait, le produit [I, {I, LST}] n'a pas échoué pour moi, c'est simplement lent.


@ M.Wizard: Quelles valeurs avez-vous utilisées? Mon MMA-V8 échoue uniquement aux grandes listes qui donnent un résultat non valorisé à la machine ... Mon installation MMA-V7 fonctionne bien. Par exemple, comparer produit [i, {i, aléatoire (1, 50000]}] avec produit [i, {i, randomreal [{. 99, 1.01}, 50000]}] et produit [i, {i, RandomReal [10, 50000]}] - Seul le milieu travaille pour moi.


@ M.Wizard: OK, j'ai soumis un rapport de bogue. WRI peut trier ce qui se passe!



4
votes

Premièrement, pour éviter la confusion, jetez un coup d'œil à un exemple dont les résultats sont tous représentant en tant que numéros de précision de machine matériels, qui doivent tous être inférieurs à xxx

Votre exemple total a déjà eu cette belle (et rapide) propriété. Voici une variante à l'aide de votre temps à l'aide de numéros de machine: xxx

Nous pouvons utiliser maintenant compile pour effectuer une fonction compilée pour effectuer cette opération efficacement: xxx

C'est beaucoup plus rapide: < Pré> XXX

En supposant que vous avez un compilateur C et Mathematica 8, vous pouvez également compiler automatiquement tout le chemin du code C. Une DLL temporaire est créée et reliée dans Mathematica au moment de l'exécution. xxx

Ceci donne des performances peu différentes de ce que la fonction mathématica intégrée aurait: xxx

Notez que Si votre produit ira vraiment au-delà de $ maxmachinenumber (ou $ minmachinenumber ), alors vous êtes mieux éteint avec appliquer [fois, liste] < / code>. Le même commentaire s'applique au total, si vos résultats peuvent obtenir ce gros: xxx


5 commentaires

Andrew, de ne pas sembler ingrat, mais j'étais déjà au courant de la compilée, c'est pourquoi j'ai déclaré: "La fonction devra être capable de retourner des fluctuations non-machines à être utiles." Est une fonction plus rapide que fois @@ dans mon exemple d'origine possible, ou est-ce juste la nature des chiffres?


Ah mon erreur, j'ai raté ce détail. Rien de simple ne saute à l'esprit jusqu'à présent qui sera meilleur que fois @@ et le même problème s'applique au total (bien que vous puissiez rarement obtenir les chiffres si grands).


C'est toujours une bonne réponse pour que quiconque lisait cette question.


+1, pour tous les gars de Wolfram pour la nouvelle fonctionnalité de compilation du code de la machine et de relier via une DLL temp. Juste besoin d'obtenir v. 8 maintenant ... comme un de côté, la DLL peut-elle être sauvée, c'est-à-dire pouvoir compiler un colis, sauvegarder la DLL et le réutiliser plus tard?


Oui, vous créeriez une DLL avec la bibliothèqueGenerate ( référence.wolfram.com/mathematica/ CCODÉGENERATOR / REF / ... ), et chargez-le à nouveau avec référence.wolfram. com / mathematica / ref / bibliothèquefonctionload.ht ml . Notez que, comme avec la compilée, ce n'est généralement que les morceaux de mathématica «C-like» qui compileront le code rapide.



3
votes

La méthode de Simon est rapide, mais elle échoue sur des valeurs négatives. Combinant avec sa réponse à mon autre question , voici ici une solution rapide qui gère les négatifs. Merci, Simon.

Fonction H2>
{0.844, -4.42943661963*10^6323240}

{0.062, -4.4294366*10^6323240}

{0.64, -4.42943661963*10^6323240}

{0.203, -4.4294366*10^6323240}


0 commentaires