【发布时间】:2010-12-13 21:57:30
【问题描述】:
我正在开发一些模板化的线性代数代码 矩阵系数类型。一种可能的类型是要做的类 模运算,天真地实现如下:
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.
};
但是,当程序以Modular<int> 系数运行时,它是几个
比使用int 系数运行时慢几倍。
我应该在“模块化”类中更改哪些内容 为了获得最佳性能?
例如,是否可以优化 a*b + c*d 之类的表达式
到(a.val_*b.val_ + c.val_*d.val_) % modulus,而不是obvious:
(((a.val_*b.val_) % modulus) + ((c.val_*d.val_ % modulus) % modulus) % modulus)
【问题讨论】:
-
它在什么编程环境中运行?你打开编译器优化了吗?
-
您可能希望在乘法之前执行归约,以防止溢出。
-
如果模数是 2 的幂,您可以使用“x & (modulus-1)”代替“x % 模数”。请注意,负 x 的结果不同,尽管 (-10 % 8 是 -2,但 -10 & (8-1) 是 6)
-
@Tom Sirgedas:如果在编译时知道模数,任何理智的编译器都会这样做。它被称为“强度降低”,因为它用较弱的运算符替换了一个较强的运算符。
-
@Jørgen Fogh:你是对的。由于负数的不同行为,我持怀疑态度,但诀窍是 AND 80000007h 然后 OR 与 FFFFFFF8h 用于负数(但这需要一个分支)。
标签: c++ performance math optimization modulo