试图降低几乎但不是很完整的数字类的速度开销

Fum*_*Eda 2 c++ optimization numbers operator-overloading

我已经实现了一个C++类,其行为与标准int类型非常相似.区别在于它有一个额外的"epsilon"概念,它代表一个小于1但大于0的微小值.一种思考方式是一个非常宽的固定点数,有32个MSB(整数)部分),32 LSB(ε部分)和中间的巨大零海.(注意:这个类和普通定点数之间的一个很大的区别是有两个符号,而不是一个:"value"和"epsilon"可以相互独立,而对于固定点,有一个符号表示全数.)

以下类可以工作,但在整个程序中引入了~2倍的速度惩罚.(该程序包含与此类无关的代码,因此该类的实际速度惩罚可能远大于2x.)我无法粘贴使用此类的代码,但我可以说以下内容:

+, -, +=, <, >并且>=是唯一使用频繁的运营商.使用setEpsilon()getInt()极为罕见.*也很少见,甚至根本不需要考虑epsilon值.

这是班级:

#include <limits>

struct int32Uepsilon {
typedef int32Uepsilon Self;

int32Uepsilon () { _value = 0;
                   _eps   = 0; }
int32Uepsilon (const int &i) { _value = i;
                               _eps   = 0; }
void setEpsilon() { _eps = 1; }
Self operator+(const Self &rhs) const { Self result = *this;
                                      result._value += rhs._value;
                                      result._eps   += rhs._eps;
                                      return result; }
Self operator-(const Self &rhs) const { Self result = *this;
                                      result._value -= rhs._value;
                                      result._eps   -= rhs._eps;
                                      return result; }
Self operator-(               ) const { Self result = *this;
                                      result._value = -result._value;
                                      result._eps   = -result._eps;
                                      return result; }
Self operator*(const Self &rhs) const { return this->getInt() * rhs.getInt(); } // XXX: discards epsilon

bool operator<(const Self &rhs) const { return (_value < rhs._value) ||
                                             (_value == rhs._value && _eps < rhs._eps); }
bool operator>(const Self &rhs) const { return (_value > rhs._value) ||
                                             (_value == rhs._value && _eps > rhs._eps); }
bool operator>=(const Self &rhs) const { return (_value >= rhs._value) ||
                                             (_value == rhs._value && _eps >= rhs._eps); }

Self &operator+=(const Self &rhs) { this->_value += rhs._value;
                                  this->_eps   += rhs._eps;
                                  return *this; }
Self &operator-=(const Self &rhs) { this->_value -= rhs._value;
                                  this->_eps   -= rhs._eps;
                                  return *this; }
int getInt() const { return(_value); }

private:
  int _value;
  int _eps;
};

namespace std {
template<>
struct numeric_limits<int32Uepsilon> {
  static const bool is_signed  = true;
  static int max() { return 2147483647; }
}
};
Run Code Online (Sandbox Code Playgroud)

上面的代码有效,但速度很慢.有没有人对如何提高性能有任何想法?我可以提供一些可能有用的提示/细节:

  • 32位肯定不足以容纳_value和_eps.实际上,使用最多24~28位_value,最多使用20位_eps.
  • 我无法衡量使用int32_t和之间的显着性能差异int64_t,因此内存开销本身可能不是问题.
  • 在_eps上饱和加法/减法会很酷,但实际上并不是必需的.
  • 请注意,_value和_eps的符号不一定相同!这打破了我第一次尝试加速这门课程.
  • 内联汇编没有问题,只要它在运行Linux的Core i7系统上与GCC一起使用即可!

Oli*_*rth 5

有一件事是尝试定义如的规范做法operator+在以下方面operator+=:

Self operator+(const Self &rhs) const { return Self(*this) += rhs; }
Run Code Online (Sandbox Code Playgroud)

这有助于返回值优化,从而消除了按值返回所需的复制构造函数.

此外,它减少了代码维护!

  • @Oli:请注意,我将lhs值传递给独立运算符+.[见本文](http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/). (2认同)