C'est très difficile question, et que je suis souvent confronté, comme je l'ai échanger un code différent dans un package pour accélérer les choses. Parfois, une régression de la performance s'accompagne d'un changement dans les algorithmes ou de la mise en œuvre, mais il peut également survenir en raison de changements dans les structures de données utilisées.
Qu'est ce qu'un bon flux de travail pour la détection de la performance des régressions dans les packages R?
Dans mon cas, j'ai tendance à avoir très spécifique des cas d'utilisation que je suis en train de prendre de la vitesse, avec fixes différents ensembles de données. Comme Spacedman écrit, il est important d'avoir un système informatique, mais c'est presque impossible: parfois, un ordinateur partagé, peut avoir d'autres processus que ralentir les choses de 10 à 20%, même quand il semble tout à fait inactif.
Mes étapes:
- Normaliser la plate-forme (par exemple une ou quelques machines, une machine virtuelle particulière, ou à une machine virtuelle + spécifiques de l'infrastructure, à la manière d'Amazon EC2 types d'instance).
- Normaliser l'ensemble de données qui sera utilisée pour accélérer les tests.
- Créer des scripts et intermédiaire fixe de sortie de données (c'est à dire enregistré .rdat fichiers) qui comportent très peu de transformations de données. Mon accent est mis sur une sorte de modélisation, plutôt que de la manipulation de données ou de transformation. Cela signifie que je veux donner exactement le même bloc de données à la modélisation de fonctions. Si, toutefois, la transformation de données est le but, alors assurez-vous que le pré-transformés/manipuler des données est aussi proche que possible de la norme à travers des tests des différentes versions du paquet. (Voir à cette question pour des exemples de memoization, cacher, etc., qui peut être utilisé pour normaliser ou de la vitesse non-focale calculs. Il fait référence à plusieurs paquets par les OP.)
- Répéter les tests plusieurs fois.
- À l'échelle les résultats relatifs à la fixe des repères, par exemple, le temps d'effectuer une régression linéaire, pour trier une matrice, etc. Cela peut permettre de "local" ou des variations transitoires dans les infrastructures, comme cela peut être dû à I/O, le système de mémoire, les paquets dépendants, etc.
-
Examiner l'établissement de profils de sortie aussi énergiquement que possible (voir à cette question pour des idées, aussi de référencement sur les outils de l'OP).
Idéalement, je suis à la recherche de quelque chose qui s'intègre avec R CMD vérifier que les alertes moi quand j'ai introduit une régression de la performance dans mon code.
Malheureusement, je n'ai pas de réponse à cette question.
Qu'est ce qu'un bon flux de travail en général?
Pour moi, c'est assez similaire à la dynamique générale de code de test: est-ce que la sortie (temps d'exécution, dans ce cas) de la reproductibilité optimale et transparente? La transparence vient de comprendre ce qui influe sur l'ensemble du temps. C'est là que Mike Dunlavey les suggestions sont importants, mais je préfère aller plus loin, avec une ligne de profiler.
Concernant une ligne de profils, voir ma précédente question, qui se réfère à des options en Python et Matlab pour d'autres exemples. Il est plus important d'examiner le temps de l'horloge, mais aussi très important de faire le suivi de l'allocation de mémoire, le nombre de fois que la ligne est exécutée, et la pile des appels en profondeur.
Quelles sont les autres langues de fournir de bons outils?
Presque toutes les autres langues ont de meilleurs outils. :) Les langages comme Python et Matlab ont la bonne et probablement familier des exemples d'outils qui peuvent être adaptés à cet effet. Bien que l'analyse de la dynamique est très important, l'analyse statique peut aider à identifier où il peut y avoir des problèmes plus sérieux. Matlab est un excellent analyseur statique qui peut rapporter lorsque les objets (par exemple, vecteurs, matrices) se développent à l'intérieur des boucles, par exemple. Il est terrible de trouver ce que via l'analyse dynamique - vous avez déjà perdu du temps d'exécution de découvrir quelque chose de ce genre, et il n'est pas toujours perceptible si l'exécution de votre contexte est assez simple (par exemple, juste quelques itérations, ou de petits objets).
Dans la langue-agnostique méthodes, vous pouvez consulter:
- Valgrind & cachegrind
- La surveillance des e/S de disque, sale tampons, etc.
- La surveillance de la RAM (Cachegrind est utile, mais vous pourriez tout simplement surveiller l'allocation de RAM, et beaucoup de détails sur l'utilisation de la RAM)
- L'utilisation de plusieurs cœurs
Est-il quelque chose qui peut être construit sur les tests unitaires, ou qui est généralement effectué séparément?
C'est difficile de répondre. Pour l'analyse statique, il peut se produire avant que l'unité de test. Pour une analyse dynamique, on peut vouloir ajouter plus de tests. Il pense que séquentielle de conception (c'est à dire à partir d'un modèle expérimental cadre): si les coûts d'exécution semblent être, dans un certain nombre de statistiques des allocations pour la modification, la même, alors pas de tests supplémentaires sont nécessaires. Si, toutefois, la méthode B semble avoir un moyen d'exécution coût de plus que la méthode A, ensuite, il faut effectuer plus de tests intensifs.
Mise à jour 1: Si j'ai peut-être si audacieux, il y a une autre question que je voudrais recommander l'inclusion, qui est: "Quels sont certains des pièges de comparer le temps d'exécution de deux versions d'un paquet?" Ceci est analogue à l'hypothèse que les deux programmes qui mettent en œuvre le même algorithme doit avoir les mêmes objets intermédiaires. Ce n'est pas exactement vrai (voir cette question - non pas que je suis la promotion de mes propres questions, ici c'est juste travailler dur pour faire les choses mieux et plus vite...conduisant à de multiples DONC des questions sur ce sujet :)). De manière similaire, les deux exécutions du même code peuvent différer dans le temps consommé en raison de facteurs autres que la mise en œuvre.
Ainsi, certains pièges qui peuvent se produire, soit dans la même langue ou dans d'autres langues, au sein de la même instance d'exécution ou de l'autre côté "à l'identique" des instances, ce qui peut affecter l'exécution:
- Collecte des ordures ménagères - les différentes implémentations de la ou des langues peut frapper la collecte des ordures dans des circonstances différentes. Cela peut faire deux exécutions semblent différents, mais il peut être très dépendante du contexte, des paramètres, des ensembles de données, etc. Le GC-obsessionnelle exécution look plus lent.
- Nouvelle mise en mémoire cache au niveau du disque, de la carte mère (ex: L1, L2, L3 caches), ou à d'autres niveaux (par exemple, memoization). Souvent, la première exécution de payer une pénalité.
-
Dynamic voltage scaling - Ce le suce. Quand il ya un problème, cela peut être l'un des plus difficiles bestioles à trouver, car il peut s'en aller rapidement. Il ressemble à cacher, mais il ne l'est pas.
- Tout emploi la priorité manager que vous ne connaissez pas.
- Une méthode utilise plusieurs cœurs ou ne astucieux des choses à propos de la façon dont le travail est morcelé entre les carottes ou les Processeurs. Par exemple, l'obtention d'un processus verrouillé à un noyau qui peut être utile dans certains scénarios. Une exécution d'un package R peut être plus de chance à cet égard, un autre paquet peut être très intelligent...
- Les variables, l'excès de transfert de données, sale caches, unflushed tampons, ... la liste est longue.
Le principal résultat est: dans l'idéal, comment doit-on tester les différences dans les valeurs attendues, sous réserve du caractère aléatoire créé par ordonnance effets? Bien, assez simple: revenir à la conception expérimentale. :)
Lorsque l'empirique des différences dans les temps d'exécution sont différentes de la "attendus" des différences, c'est génial d'avoir activé le système supplémentaire et de l'exécution de la surveillance, de sorte que nous n'avons pas à ré-exécuter les expériences jusqu'à ce que nous sommes en bleu dans le visage.