8
votes

moyen efficace de prendre des pouvoirs d'un vecteur

J'ai écrit un code qui utilise numériquement des polynômes légendres jusqu'à un certain N-ème ordre. Par exemple: xxx

si le vecteur x est long, cela peut devenir lent. J'ai vu qu'il existe une différence de performance entre dire x. ^ 4 et x. * X. * X. X et pensé que je pourrais utiliser cela pour améliorer mon code. J'ai utilisé Timeit et trouvé que pour: xxx

f4 est plus rapide par un facteur 2 que le reste. Cependant, quand je vais à x. ^ 6 il y a très peu de différence entre (x. * X. X). ^ 2 et x. * X. * x. * x. * x. * x (tandis que toutes les autres options sont plus lentes).

est là pour dire ce qui sera le moyen le plus efficace de prendre une puissance d'un vecteur ? Pouvez-vous expliquer pourquoi il y a une telle différence de performance?


0 commentaires

3 Réponses :


8
votes

Ce n'est pas une réponse exactement à votre question, mais cela peut résoudre votre problème:

x2 = x.*x; % or x.^2 or power(x,2), whichever is most efficient
p = ((((6435*x2-12012)*x2+6930)*x2-1260)*x2+35)/128


0 commentaires

1
votes

Voici quelques pensées:

puissance (x, 4) code> et x. ^ 4 code> sont équivalents (juste lire le doc). P> x. * x. * x. x x code> est probablement optimisé à quelque chose comme x. ^ 2. ^ 2 code> p>


x. ^ 2. ^ 2 code> est probablement évalué comme suit: Prenez le carré de chaque élément (rapide) et prenez à nouveau le carré de celui-ci (à nouveau rapide). P>

x. ^ 4 code> est probablement directement évalué comme suit: Prenez la quatrième puissance de chaque élément (lent). P>

Il n'est pas si étrange de voir que 2 opérations rapides prennent moins de temps que 1 opération lente . Dommage que l'optimisation ne soit pas effectuée dans le boîtier de puissance 4, mais elle ne fonctionnera peut-être pas toujours à un coût (vérification des entrées, mémoire?). P>


sur les timings: En fait, il y a beaucoup plus de différence qu'un facteur 2! P>

Lorsque vous les appelez dans une fonction maintenant, la fonction de fonction est ajoutée dans chaque cas, rendant les différences relatives plus petites: p> xxx pré>

donnera:

Elapsed time is 0.034826 seconds.
Elapsed time is 0.029186 seconds.
Elapsed time is 0.003891 seconds.
Elapsed time is 0.003840 seconds.


4 commentaires

L'optimisation qui est probablement faite sur x. * X. * X. X se comporte étrangement. J'ai essayé x. * J'aurais attendu des bosses; Par exemple, le cas "8" (=> x. ^ 2. ^ 2. ^ 2 : trois opérations de puissance) devrait prendre moins de temps que "7" (=> plus d'opérations de puissance)


@LUISMENDO Je ne sais pas comment vérifier, mais je pouvais imaginer que cela ne fait que 1 étape (aucune optimisation imbriquée). Pour 7, il réduirait alors quelque chose comme: x. ^ 2 * x. ^ 2 * x. ^ 2. * x qui ne serait pas plus lent que x. ^ 2 * x. ^ 2 * x. ^ 2. * x. ^ 2 pour 8. Si cela faisait 8 ans était plus rapide que de faire 7 de cette façon, Mathworks aurait probablement impliqué ce type d'optimisation dans la fonction de puissance.


Oui, cela pourrait être l'explication: pas de nidification


@ Dennisjaharuddin, je pense que tu as raison. Consultez ma réponse (que je composait lorsque vous avez répondu) - La nidification est étonnamment 2 fois plus lente pour la 16ème puissance.



1
votes

Il semble que Mathworks ait des carrés de boîtes spéciales dans sa fonction de puissance (malheureusement, tout est intégré à la source fermée que nous ne pouvons pas voir). Dans mes tests sur R2013B, il apparaît comme si . ^ Code>, alléaire code> et realppow code> Utilisez le même algorithme. Pour les carrés, je crois qu'ils ont une bloquée spéciale pour être x. * X code>. xxx pré>

pour cubes, l'histoire est différente. Ils ne sont plus spéciaux. Encore une fois, . ^ Code>, alléaire code> et realppow code> Tous sont similaires, mais beaucoup plus lent cette fois: p> xxx Pré>

Sautons à la 16ème puissance pour voir comment ces algorithmes échelle: p> xxx pré>

donc: . ^ code>, CODE> et REALLOW CODE> Tous courir dans une heure constante en ce qui concerne l'exposant, sauf s'il s'agissait d'une boîte spéciale (-1 semble également avoir été une boîte spéciale). Utilisation de l'expression exp (n * journal (x)) code> Trick est également une durée constante en ce qui concerne l'exposant et plus vite. Le seul résultat que je ne comprends pas tout à fait pourquoi la quille répétée est plus lente que la multiplication. P>

comme prévu, augmentant la taille de x code> par un facteur de 100 augmente le temps de la même manière Pour tous les algorithmes. P>

Alors, morale de l'histoire? Lorsque vous utilisez des exposants entier scalaire, faites toujours la multiplication vous-même. Il y a beaucoup de smarts dans puissance code> et amis (l'exposant peut être un point flottant, vecteur, etc.). Les seules exceptions sont les mêmes exceptions que Mathworks a effectué l'optimisation pour vous. En 2013b, il semble être x ^ 2 code> et x ^ (- 1) code>. Espérons qu'ils vont ajouter davantage au fil du temps. Mais, en général, l'exponentiation est difficile et la multiplication est facile. Dans le code sensible à la performance, je ne pense pas que vous puissiez vous tromper en tapant toujours x. * X. * X x code>. (Bien sûr, dans votre cas, suivez les conseils de Luis et utilisez les résultats intermédiaires dans chaque terme!) P>

function powerTest(x)

f{1} = @() x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x;
f{2} = @() x.^2.^2.^2.^2;
f{3} = @() exp(16.*log(x));
f{4} = @() x.^16;
f{5} = @() power(x,16);
f{6} = @() realpow(x,16);

for i = 1:length(f)
    t(i) = timeit(f{i});
end

[t,idxs] = sort(t);
fcns = f(idxs);

for i = 1:length(fcns)
    fprintf('%.1fx (%.1fms):\t%s\n',t(i)/t(1),t(i)*1e3,func2str(fcns{i}));
end


0 commentaires