Je développe un code d'algèbre linéaire qui est modélisé sur le type de coefficient de matrice . L'un des types possibles est une classe pour faire arithmétique modulaire, naïvement mis en œuvre comme suit:optimisation des calculs arithmétiques modulaires en C++
template<typename val_t> // `val_t` is an integer type
class Modular
{
val_t val_;
static val_t modulus_;
public:
Modular(const val_t& value) : val_(value) { };
static void global_set_modulus(const val_t& modulus) { modulus_ = modulus; };
Modular<val_t>& operator=(const Modular<val_t>& other) { val_ = other.val_; return *this; }
Modular<val_t>& operator+=(const Modular<val_t>& other) { val_ += other.val_; val_ %= modulus_; return *this; }
Modular<val_t>& operator-=(const Modular<val_t>& other) { val_ -= other.val_; val_ %= modulus_; return *this; }
Modular<val_t>& operator*=(const Modular<val_t>& other) { val_ *= other.val_; val_ %= modulus_; return *this; }
Modular<val_t>& operator/=(const Modular<val_t>& other) { val_ *= other.inverse().val_; val_ %= modulus_; return *this; }
friend Modular<val_t> operator+(const Modular<val_t>& a, const Modular<val_t>& b) { return Modular<val_t>((a.val_ + b.val_) % Modular<val_t>::modulus_); };
friend Modular<val_t> operator-(const Modular<val_t>& a, const Modular<val_t>& b) { return Modular<val_t>((a.val_ - b.val_) % Modular<val_t>::modulus_); };
// ...etc.
};
Cependant, lorsque le programme fonctionne avec les Modular<int>
coefficients, il est plusieurs fois plus lent que lorsqu'il fonctionne avec int
coefficients .
Quelles sont les choses que je devrais changer dans la classe "Modulaire" dans afin d'obtenir des performances maximales?
Par exemple, il est possible d'optimiser les expressions comme a*b + c*d
à (a.val_*b.val_ + c.val_*d.val_) % modulus
, et au lieu de la obvious:
(((a.val_*b.val_) % modulus) + ((c.val_*d.val_ % modulus) % modulus) % modulus)
Dans quel environnement de programmation est-il exécuté? Avez-vous mis en place l'optimisation du compilateur? – wallyk
Vous pouvez effectuer une réduction avant la multiplication pour empêcher le débordement. –
Si le module est une puissance de 2, vous pouvez utiliser "x & (module-1)" au lieu de "module x%". Notez que les résultats diffèrent pour x négatif, bien que (-10% 8 soit -2, mais -10 & (8-1) soit 6) –