Résumé:
Je recherche le moyen le plus rapide de calculer
(int) x / (int) y
sans obtenir une exception pour y==0
. Au lieu de cela, je veux juste un résultat arbitraire.
Contexte:
Lors du codage d'algorithmes de traitement d'image, j'ai souvent besoin de diviser par une valeur alpha (accumulée). La variante la plus simple est le code C simple avec arithmétique entière. Mon problème est que j'obtiens généralement une erreur de division par zéro pour les pixels de résultat avec alpha==0
. Cependant, ce sont exactement les pixels où le résultat n'a aucune importance: je me fiche des valeurs de couleur des pixels avec alpha==0
.
Détails:
Je recherche quelque chose comme:
result = (y==0)? 0 : x/y;
ou
result = x / MAX( y, 1 );
x et y sont des entiers positifs. Le code est exécuté un grand nombre de fois dans une boucle imbriquée, je cherche donc un moyen de me débarrasser du branchement conditionnel.
Lorsque y ne dépasse pas la plage d'octets, je suis satisfait de la solution
unsigned char kill_zero_table[256] = { 1, 1, 2, 3, 4, 5, 6, 7, [...] 255 };
[...]
result = x / kill_zero_table[y];
Mais cela ne fonctionne évidemment pas bien pour les plus grandes gammes.
Je suppose que la dernière question est la suivante: quel est le piratage le plus rapide qui change de 0 à une autre valeur entière, tout en laissant toutes les autres valeurs inchangées?
Clarifications
Je ne suis pas sûr à 100% que le branchement soit trop cher. Cependant, différents compilateurs sont utilisés, donc je préfère le benchmarking avec peu d'optimisations (ce qui est en effet discutable).
Bien sûr, les compilateurs sont excellents en ce qui concerne le twiddling, mais je ne peux pas exprimer le résultat "don't care" en C, donc le compilateur ne pourra jamais utiliser la gamme complète des optimisations.
Le code doit être entièrement compatible C, les principales plates-formes sont Linux 64 bits avec gcc & clang et MacOS.
y += !y
- être ? Aucune branche nécessaire pour calculer cela. Vous pouvez comparer les x / (y + !y)
contre x / max(y, 1)
et peut - être aussi y ? (x/y) : 0
. Je suppose qu'il n'y aura aucune branche dans l'un ou l'autre, du moins avec les optimisations activées.
0
sections alpha sont énormes et contiguës. Il y a un endroit pour bidouiller avec les micro-optimisations, et les opérations par pixel sont exactement cet endroit.