在C++中优化模运算

Ric*_*rri 2 c++ math optimization performance modulo

我正在开发一些在矩阵系数类型上模板化的线性代数代码.其中一种可能的类型是进行模运算的类,天真地实现如下:

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.
};
Run Code Online (Sandbox Code Playgroud)

但是,当程序使用Modular<int>系数运行时,它比使用int系数运行时慢几倍.

为了获得最佳性能,我应该在"模块化"类中改变哪些内容?

举例来说,就是可以优化般的表情a*b + c*d(a.val_*b.val_ + c.val_*d.val_) % modulus的,取而代之的是明显的:

(((a.val_*b.val_) % modulus) + ((c.val_*d.val_ % modulus) % modulus) % modulus)
Run Code Online (Sandbox Code Playgroud)

Edw*_*nge 8

是.有可能的.你想要查找的是"表达模板"并从那里开始.从那时起,您将不得不构建一些元程序逻辑来优化/简化表达式.这不是一项微不足道的任务,但这不是你所要求的.

NVM - 这是微不足道的:

int count = 0;
int modulus() { count++; return 10; }

template < typename T >
struct modular
{
  modular(T v) : value_(v) {}

  T value() const { return value_; }
  void value(T v) { value_ = v; }

  typedef modular<T> modular_type;
  typedef T raw_type;
private:
  T value_;
};

template < typename LH, typename RH >
struct multiply
{
  multiply(LH l, RH r) : lh(l), rh(r) {}

  typedef typename LH::modular_type modular_type;
  typedef typename LH::raw_type raw_type;

  raw_type value() const { return lh.value() * rh.value(); }

  operator modular_type () const { return modular_type(value() % modulus()); }

private:
  LH lh; RH rh;
};

template < typename LH, typename RH >
struct add
{
  add(LH l, RH r) : lh(l), rh(r) {}

  typedef typename LH::modular_type modular_type;
  typedef typename LH::raw_type raw_type;

  raw_type value() const { return lh.value() + rh.value(); }
  operator modular_type () const { return modular_type(value() % modulus()); }

private:
  LH lh; RH rh;
};

template < typename LH, typename RH >
add<LH,RH> operator+(LH const& lh, RH const& rh)
{
  return add<LH,RH>(lh,rh);
}

template < typename LH, typename RH >
multiply<LH,RH> operator*(LH const& lh, RH const& rh)
{
  return multiply<LH,RH>(lh,rh);
}

#include <iostream>

int main()
{
  modular<int> a = 5;
  modular<int> b = 7;
  modular<int> c = 3;
  modular<int> d = 8;

  std::cout << (5*7+3*8) % 10 << std::endl;

  modular<int> result = a * b + c * d;
  std::cout << result.value() << std::endl;

  std::cout << count << std::endl;

  std::cin.get();
}
Run Code Online (Sandbox Code Playgroud)

如果你很聪明,你可以在构造函数中使用%来实现模块化,因此它总是模块化的; 你还要检查以确保LH和RH与SFINAE垃圾兼容,以防止操作员在任何时候杀死它.您还可以使模数为模板参数,并提供元函数来访问它.无论如何......你去吧.

编辑:BTW,您可以使用相同的技术使您的矩阵计算更快.您可以制作这些内容,然后在分配结果时逐个元素地进行数学运算,而不是为一系列操作中的每个操作创建一个新矩阵.互联网上有关于它的文章和所有内容,将它与FORTRAN等进行比较.是元编程的第一个用途之一,就像在C++中使用模板一样.另外在书中http://www.amazon.com/Scientific-Engineering-Introduction-Advanced-Techniques/dp/0201533936 < - 请记住,虽然"高级技术"是在94:p.它今天没那么重要.