2010-07-10 5 views
4

J'ai écrit un type Int128 et ça marche très bien. Je pensais pouvoir améliorer ses performances avec une idée simple: améliorer les opérations de décalage qui sont un peu maladroites. Parce qu'ils sont fortement utilisés dans la multiplication et la division, une amélioration aurait un effet d'entraînement.Est-ce que MSIL a des instructions ROL et ROR?

J'ai donc commencé à créer une méthode dynamique (pour passer bas et tourner haut), seulement pour découvrir qu'il n'y a pas OpCodes.Rol ou OpCodes.Ror instructions.

Est-ce possible en IL?

+0

Même s'il s'avère qu'il n'existe pas de code op CIL pour les rotations de bits, le compilateur JIT peut encore être assez intelligent pour mapper plusieurs op-codes CIL aux instructions ROL et ROR sur l'ensemble d'instructions de la machine sous-jacente. (Je ne pense pas que le compilateur JIT soit * intelligent *, mais au moins c'est possible). Je veux dire: je ne m'inquiéterais pas trop. Comparé au langage d'assemblage réel, le code CIL semble très inefficace de toute façon, mais le compilateur JIT le soulagera probablement un peu. – stakx

Répondre

4

No.

Vous devez le mettre en œuvre avec le bit décale

UInt64 highBits = 0; 
UInt64 lowBits = 1; 
Int32 n = 63; 
var altShift = (n - 63); 

var lowShiftedOff = (n - 63) > 0 ? 0 : (lowBits << n); 
var highShiftedOff = (n - 63) > 0 ? 0 : (highBits << n); 

var highResult = (UInt64)(highShiftedOff | (altShift > 0 ? (lowBits << altShift - 1) : 0)); 
var lowResult= (UInt64)(lowShiftedOff | (altShift > 0 ? (highBits << altShift - 1) : 0)); 
+1

Merci. Tu as confirmé ce que je craignais. J'ai creusé dans BigInteger de .NET 4.0 pour voir comment ils l'ont fait et maintenant je ne me sens pas si mal à propos de la mienne. – Tergiver

+1

Non seulement c'est mauvais, mais j'avais négligé que SHL et SHR ne regardent que les 5 derniers bits (pour U/Int32) ou 6 (pour U/Int64) de l'opérande de décalage, créant effectivement un module pour la valeur de décalage complet . C'est une grande peine quand on essaie de faire bouger les bits, et je n'arrive pas à comprendre pourquoi il a été implémenté comme ça. – codekaizen

+0

Les opérandes de décalage ne sont définis que pour les décalages inférieurs à la taille du type concerné, car le décalage de plus de * n * bits pour un type * n * -bit n'a pas beaucoup de sens. La norme (ECMA 335: §3.59) dit: 'La valeur de retour n'est pas spécifiée si 'shiftAmount' est supérieur ou égal à la largeur de 'value'.' – porges

0

Pour répondre en partie à cette question 7 ans plus tard, au cas où quelqu'un devrait en avoir besoin.

Vous pouvez utiliser ROR/ROL dans .Net. MSIL ne contient pas directement les opérations ROR ou ROL, mais il existe des modèles qui permettront au compilateur JIT de générer ROR et ROL. RuyJIT (.Net et .Net core) supporte cela.

Les détails de l'amélioration. Net Core pour utiliser ce modèle était discussed here et un mois plus tard. Le code de base de .Net était updated to use it.

En regardant le implementation of SHA512 nous trouvons des exemples de ROR:

public static UInt64 RotateRight(UInt64 x, int n) { 
     return (((x) >> (n)) | ((x) << (64-(n)))); 
    } 

et extension par même modèle ROL:

public static UInt64 RotateLeft(UInt64 x, int n) { 
     return (((x) << (n)) | ((x) >> (64-(n)))); 
    } 

Pour ce faire sur entier 128 bits vous pouvez traiter comme deux 64 -bit, puis ET pour extraire "carry", ET pour effacer la destination et OU pour appliquer. Cela doit être reflété dans les deux directions (basse -> haute et haute - basse). Je ne vais pas m'embêter avec un exemple puisque cette question est un peu ancienne.