Je viens d'utiliser ~ 1 milliard comme compte pour un z-index
CSS, et je réfléchissais aux comparaisons qui doivent se faire. Existe-t-il une différence de performance au niveau des UAL dans les comparaisons entre les très grands nombres et les très petits?
Par exemple, l'un de ces deux extraits serait-il plus coûteux que l'autre?
snippet 1
for (int i = 0; i < 10000000; i++){
if (i < 10000000000000) {
//do nothing
}
}
snippet 2
for (int i = 0; i < 10000000; i++){
if (i < 1000) {
//do nothing
}
}
performance
cpu
Viziionary
la source
la source
CMP
instruction individuelle de la machine sera plus lente si ellei
est plus grande.Réponses:
Chaque processeur sur lequel j'ai travaillé effectue la comparaison en soustrayant l'un des opérandes de l'autre, en ignorant le résultat et en laissant les indicateurs du processeur (zéro, négatif, etc.). Comme la soustraction est effectuée en une seule opération, le contenu des opérandes importe peu.
La meilleure façon de répondre à la question est de compiler votre code en assembleur et de consulter la documentation du processeur cible pour connaître les instructions générées. Pour les processeurs Intel actuels, il s'agirait du Manuel du développeur de logiciels pour architectures Intel 64 et IA-32 .
La description de l'
CMP
instruction ("comparer") se trouve dans le volume 2A, page 3-126 ou page 618 du document PDF, et décrit son fonctionnement comme suit:Cela signifie que le deuxième opérande est étendu si nécessaire au signe, soustrait du premier opérande et que le résultat est placé dans une zone temporaire du processeur. Ensuite, les indicateurs d'état sont définis de la même manière que pour l'
SUB
instruction ("soustraire") (page 1492 du document PDF).La documentation
CMP
ou laSUB
documentation ne mentionnent pas que les valeurs des opérandes ont une incidence sur le temps de latence. Par conséquent, toute valeur que vous utilisez est sûre.la source
C'est très improbable, à moins de passer d'un nombre petit à un nombre élevé, change votre type de chiffre, par exemple d'
int
unlong
. Même dans ce cas, la différence pourrait ne pas être significative. Il est plus probable que vous constatiez une différence si votre langage de programmation bascule en silence sur l'arithmétique en précision arbitraire sous les couvertures.Néanmoins, votre compilateur peut effectuer des optimisations intelligentes dont vous n'êtes pas au courant. La façon dont vous le découvrez est de mesurer. Exécutez un profileur sur votre code; voir quelles comparaisons prennent le plus longtemps. Ou tout simplement démarrer et arrêter une minuterie.
la source
De nombreux processeurs ont de "petites" instructions capables d'effectuer des opérations arithmétiques, notamment des comparaisons, sur certains opérandes spécifiés immédiatement. Les opérandes autres que ces valeurs spéciales doivent soit utiliser un format d'instruction plus grand, soit, dans certains cas, utiliser une instruction "charger la valeur de la mémoire". Dans le jeu d'instructions ARM Cortex-M3, par exemple, il existe au moins cinq façons de comparer une valeur à une constante:
La première forme est la plus petite; les deuxième et troisième formes peuvent ou non être exécutées aussi rapidement, en fonction de la vitesse de la mémoire à partir de laquelle le code est extrait. La quatrième forme sera presque certainement plus lente que les trois premières, et la cinquième encore plus lente, mais cette dernière peut être utilisée avec n'importe quelle valeur 32 bits.
Sur les processeurs x86 plus anciens, les instructions de comparaison de forme abrégée s'exécutent plus rapidement que celles de forme longue, mais de nombreux processeurs plus récents convertissent les formulaires long et court en la même représentation lors de leur première extraction et stockent cette représentation uniforme dans le cache. Ainsi, alors que les contrôleurs intégrés (comme ceux que l'on trouve sur de nombreuses plates-formes mobiles) auront une différence de vitesse, de nombreux ordinateurs x86 ne le feront pas.
Notez également que dans de nombreux cas où une constante est fortement utilisée dans une boucle, un compilateur n'aura à charger la constante dans un registre qu'une seule fois - avant le début de la boucle - rendant les distinctions temporelles fictives. D'un autre côté, il y a des situations, même dans de petites boucles, où cela ne se produit pas toujours. Si une boucle est petite mais fortement exécutée, il peut parfois y avoir une performance majeure entre les comparaisons impliquant des valeurs immédiates courtes et celles impliquant des valeurs plus longues.
la source
La réponse courte à cette question est non , il n'y a pas de différence de temps pour comparer deux nombres en fonction de leur magnitude, en supposant qu'ils sont stockés dans le même type de données (par exemple, les deux inits 32 bits ou les bits longs de 64 bits).
De plus, jusqu'à la taille de mot de l' ALU , il est extrêmement improbable que la comparaison de deux nombres entiers prenne plus d'un cycle d'horloge, car il s'agit d'une opération triviale équivalente à une soustraction. Je pense que chaque architecture à laquelle j'ai eu affaire avait une comparaison d’entiers sur un seul cycle.
Les seuls cas auxquels je peux penser que j'ai rencontrés dans lesquels la comparaison de deux nombres n'était pas une opération à cycle unique sont les suivants:
la source
@ La réponse de RobertHarvey est bonne; considérez cette réponse comme un complément à la sienne.
Vous devriez également envisager la prévision de branche :
Fondamentalement, dans votre exemple, si l’
if
instruction dans la boucle renvoie toujours la même réponse, le système peut l’optimiser en devinant correctement le sens de la branche. Dans votre exemple, étant donné que l'if
instruction dans le premier cas renvoie toujours le même résultat, son exécution sera légèrement plus rapide que dans le deuxième cas.Excellente question de débordement de pile sur le sujet
la source
Cela dépend de la mise en œuvre, mais ce serait très, très improbable .
J'avoue que je n'ai pas lu les détails de la mise en œuvre des différents moteurs de navigateur et que CSS ne spécifie aucun type de stockage particulier pour les numéros. Mais je pense qu’il est raisonnable de supposer que tous les principaux navigateurs utilisent des nombres à virgule flottante double précision 64 bits ("doubles", pour emprunter un terme de C / C ++) afin de gérer la plupart de leurs besoins numériques en CSS. , car c’est ce que JavaScript utilise pour les nombres, et l’utilisation du même type facilite donc l’intégration.
Du point de vue de l'ordinateur, tous les doubles transportent la même quantité de données: 64 bits, que la valeur soit 1 ou -3,14 ou 1000000 ou 1e100 . La durée nécessaire pour effectuer une opération sur ces chiffres ne dépend pas de la valeur réelle de ces chiffres, car elle fonctionne toujours sur le même nombre de données. Il y a un compromis en faisant les choses de cette façon, en ce que les doubles ne peuvent pas représenter avec précision tous les nombres (ou même tous les nombres dans leur intervalle), mais ils peuvent être assez proches pour la plupart des choses, et le genre de choses que CSS ne fait pas numériquement assez exigeant pour avoir besoin de plus de précision que cela. Combinez cela avec les avantages de la compatibilité directe avec JavaScript et vous obtenez un cas assez solide pour les doublons.
Il n'est pas impossible que quelqu'un implémente CSS à l'aide d'un codage à longueur variable pour les nombres. Si quelqu'un utilisait un codage de longueur variable, alors comparer avec de petits nombres coûterait moins cher que comparer avec de grands nombres, car les grands nombres ont plus de données à traiter . Ces types d’encodage peuvent être plus précis que les fichiers binaires, mais ils sont également beaucoup plus lents et, pour CSS en particulier, les gains de précision ne sont probablement pas suffisants pour valoir les performances. Je serais très surpris d'apprendre que n'importe quel navigateur fait les choses de cette façon.
Maintenant, en théorie, il y a une exception possible à tout ce que j'ai dit plus haut: comparer avec zéro est souvent plus rapide que de comparer avec d'autres chiffres . Ce n'est pas parce que zéro est court (si c'était la raison, alors 1 devrait être aussi rapide, mais ce n'est pas le cas). C'est parce que zéro vous permet de tricher. C'est le seul nombre où tous les bits sont désactivés. Par conséquent, si vous savez qu'une des valeurs est zéro, vous n'avez même pas à regarder l'autre valeur sous forme de nombre: si l'un des bits est actif, il n'est pas égal à zéro, puis il suffit de regarder un bit pour voir s'il est supérieur ou inférieur à zéro.
la source
Si ce code était interprété à chaque fois qu'il était exécuté, il y aurait une différence, car la mise en place de marques et d'interprétations prend plus de temps
10000000000000
par rapport à1000
. Cependant, il s’agit de la première optimisation évidente des interprètes dans ce cas: tokenise une fois et interprète les jetons.la source