J'ai une méthode simple qui convertit un tableau d'un type à un autre. Je voulais savoir quelle méthode est le plus rapide. Mais jusqu'à présent, je reçois des résultats différents à partir desquels je ne peux pas conclure quelle méthode est vraiment plus rapide par laquelle la marge.
Étant donné que la conversion ne concerne que l'allocation de mémoire, la lecture de la matrice et la conversion de valeurs que je suis surprise que les valeurs ne sont pas plus stables. Je voulais savoir comment je peux faire des mesures précises qui sont significatives et de ne pas changer d'un jour à l'autre. Les différences sont d'environ 20% d'un jour à l'autre. p>
Il y a bien sûr des différences entre le mode Jiter of .NET 3.5 et 4.0, le mode de débogage et de sortie, qui n'exécute pas l'exécutable sous un débogueur (désactive les optimisations JIT jusqu'à ce que vous la désactivez), génération de code du compilateur C # entre débogage et libération (principalement des opérations NOP et plus de variables temporaires dans le code IL). p> je reçois alors p> à partir de ceci, il ressemble à la variante Safe Dumb Safe est plus rapide que toute variante dangereuse Bien que les limites Vérifiez que l'élimination des méthodes dangereuses devrait le rendre au moins aussi rapide sinon plus rapide.
Juste pour le plaisir, j'ai également compilé le même code IL via LCG (DynamicMethod) qui semblent être encore plus lents que l'une quelconque de ces méthodes, bien que le coût supplémentaire de l'invocation des délégués ne semble pas jouer un rôle aussi important ici. P> La boucle pour exécuter ce code 10 millions de fois qui devrait produire des résultats stables. Pourquoi je vois des différences ici du tout? En utilisant le temps réel comme priorité de processus n'a pas non plus aidé (Psexec -RealTime exécutable). Comment puis-je obtenir des nombres fiables? p> Mes tests ont inclus P> Si j'utilise un profileur, je ne suis pas sûr s'il faussera encore plus les mesures. Comme il interrompt ma requête de temps en temps pour obtenir les piles d'appels, il détruira certainement une localité de cache qui pourrait faciliter la performance. S'il y a une approche avec une meilleure localité de cache (données), je ne pourrai pas le trouver avec un profileur. P> EDIT1: strong>
Prendre en compte que je n'ai pas de système d'exploitation de temps réel, je fais maintenant de mes mesures. Étant donné que pour un fil, j'ai une fenêtre de temps de 15 ms accordée au planificateur Windows, je peux conserver le planificateur si je mesure plus de 15 ms. Si je mesure trop bientôt, je me retrouverai avec de très petits comptes de tiques qui ne me diront pas beaucoup. p> Pour obtenir des valeurs stables, j'ai besoin d'une durée suffisamment longue pour laisser le système d'exploitation faire ce qu'il fait de manière régulière. Des tests empiriques ont montré que plus de 30 secondes est un bon moment, une mesure devrait prendre. P> Cette période de temps est ensuite divisée en échantillons de temps de temps qui sont bien inférieurs à 15 ms. Ensuite, je vais obtenir des informations de synchronisation pour chaque échantillon. Des échantillons, je peux extraire min / max et moyenne. De cette façon, je peux aussi voir les premiers effets d'initialisation.
Le code ressemble maintenant à ce p> Les valeurs de ces tests varient toujours (<10%) mais je pense que si je crée un tableau d'histogramme de mes valeurs et déposez le 10% de valeurs les plus élevées susceptibles du système d'exploitation, GC, ... Je peux obtenir des chiffres vraiment stables que je peux faire confiance. P> Samplesize: 100, min 25, max 86400, moyenne 28 614631 P> Edit2: strong>
Les histogrammes montrent que les valeurs mesurées ne sont pas aléatoires. Ils ressemblent à un Distribution Landau qui devrait me donner avec les algorithmes d'approximation de droite valeurs stables. Je souhaite à .net existerait quelque chose comme root où je peux interagirement d'installer la bonne fonction de distribution à mes données et obtenez les résultats. p> Le code pour générer l'histogramme avec le commandes MSChart est ci-dessous: p>
P>
4 Réponses :
Je suppose que cela fonctionnerait avec mono sous Linux? Pour éviter l'influence de l'environnement multitâche, vous pouvez démarrer n'importe quel programme avec
time program
Je penserais que fonctionnant sous Mono pourrait théoriquement vous donner des résultats très différents de fonctionnement sous Windows.
Oui, mais peut-être des nombres plus stables, qui pourraient être intéressants, si vous êtes intéressé, même dans des gains de petite taille.
Je ne suis pas intéressé par le temps de la CPU. Puisque j'ai accès à la mémoire de la L1, L2 ou de la mémoire réelle (cache Miss), je dois mesurer la latence entre les différentes approches. Je peux par exemple Consommez plus de CPU lorsque je peux épargner un accès de mémoire coûteux (calculez l'index de la matrice à l'intérieur des registres au lieu d'utiliser une variable TEMP). Pour cela, j'ai besoin de l'heure de fonctionnement totale.
Vous parlez d'une différence moyenne d'environ un centième d'une nanoseconde par appel de méthode. Windows ne prétend pas être un système d'exploitation en temps réel; Ces mesures sont à peu près aussi stables que vous obtiendrez. P>
et, au fait, La jitter va em> Éliminer la vérification des limites dans votre CastSafe code> méthode . Je serais très surpris si vous pouvez trouver quelque chose plus rapidement que cela. P>
(Si le goulot d'étranglement est CPU, vous pouvez améliorer les performances en utilisant parallel.for code> plutôt qu'un broil pour code> boucle, mais pour déterminer que vous devez tester les données du monde réel. Par exemple, le comportement du cache va être considérablement différent pour une matrice de 43 INTS que pour un réseau de 43 000 000 INTS.) P>
Vous impliquez que j'essaie avec mon processeur de 2GHz pour mesurer les choses en dessous de 1 / 100n. Cela signifierait que j'essaie de mesurer avec une précision de 1/50 instruction (en moyenne). Ce n'est pas le cas. Je veux mesurer suffisamment court pour limiter l'influence du système d'exploitation et suffisamment longtemps à la moyenne du bruit aléatoire causé par le planificateur de système d'exploitation. Parallel.for signifierait que pour chaque nombre que vous souhaitez convertir, vous invoquez un délégué. C'est waaaay à cher.
@Alois: C'est pourquoi j'ai dit que je serais surpris si vous pouvez trouver quoi que ce soit plus rapidement que votre méthode code> SafeCast code>. Vous avez déjà fait autant que vous pouvez - étant donné que vous utilisez .NET sur Windows - pour "limiter l'influence du système d'exploitation" et "la moyenne de bruit aléatoire causé par le planificateur d'exploitation".
chronomètre n'est pas si précis, essayez d'utiliser HighResClock P>
http://netcode.ru/dotnet/?lang=&katid= 30 & Skatide = 261 & Artid = 7113 P>
Ne vous attendez pas à des mesures précises à la nano-seconde, car quelqu'un d'autre a écrit, Win7 n'est pas un système d'exploitation en temps réel. P>
Aussi, après GC.Collect (), vous voudrez peut-être mettre GC.WAITFORPENDENDINAIRINALISÉS (); P>
Le chronomètre porte le queryPerformCounter / la fréquence juste de la même manière que votre lien. Je suis conscient des pièges de DateTime qui n'a que 16 ms de précision. Mais QueryPerformEcanceCounter a également ses problèmes si la carte mère ne fournit pas de chronométrage de haute précision utilise le compteur de timbres temporel de la CPU qui donne des valeurs différentes sur chaque processeur qui devient une maux de tête sur des machines multi-nœuds.
J'ai modifié ma question initiale avec la conclusion que les chiffres n'étaient pas aléatoires mais suivent une distribution (ressemble à une distribution Landau) où je peux utiliser des algorithmes de montage pour obtenir la valeur maximale avec le vrai chronométrage le plus probable. p>