私は(多変量)の数値範囲を反復処理するためにいくつかのコードを持っている:ループの高速化の範囲(C++ 11)
#include <array>
#include <limits>
#include <iostream>
#include <iterator>
template <int N>
class NumericRange : public std::iterator<double, std::input_iterator_tag>
{
public:
NumericRange() {
_lower.fill(std::numeric_limits<double>::quiet_NaN());
_upper.fill(std::numeric_limits<double>::quiet_NaN());
_delta.fill(std::numeric_limits<double>::quiet_NaN());
}
NumericRange(const std::array<double, N> & lower, const std::array<double, N> & upper, const std::array<double, N> & delta):
_lower(lower), _upper(upper), _delta(delta) {
_state.fill(std::numeric_limits<double>::quiet_NaN());
}
const std::array<double, N> & get_state() const {
return _state;
}
NumericRange<N> begin() const {
NumericRange<N> result = *this;
result.start();
return result;
}
NumericRange<N> end() const {
NumericRange<N> result = *this;
result._state = _upper;
return result;
}
bool operator !=(const NumericRange<N> & rhs) const {
return in_range();
// return ! (*this == rhs);
}
bool operator ==(const NumericRange<N> & rhs) const {
return _state == rhs._state && _lower == rhs._lower && _upper == rhs._upper && _delta == rhs._delta;
}
const NumericRange<N> & operator ++() {
advance();
if (! in_range())
_state = _upper;
return *this;
}
const std::array<double, N> & operator *() const {
return _state;
}
void start() {
_state = _lower;
}
bool in_range(int index_to_advance = N-1) const {
return (_state[ index_to_advance ] - _upper[ index_to_advance ]) < _delta[ index_to_advance ];
}
void advance(int index_to_advance = 0) {
_state[ index_to_advance ] += _delta[ index_to_advance ];
if (! in_range(index_to_advance)) {
if (index_to_advance < N-1) {
// restart index_to_advance
_state[index_to_advance] = _lower[index_to_advance];
// carry
++index_to_advance;
advance(index_to_advance);
}
}
}
private:
std::array<double, N> _lower, _upper, _delta, _state;
};
int main() {
std::array<double, 7> lower{{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}};
std::array<double, 7> upper{{1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}};
std::array<double, 7> delta{{0.03, 0.06, 0.03, 0.06, 0.03, 0.06, 0.03}};
NumericRange<7> nr(lower, upper, delta);
int c = 0;
for (nr.start(); nr.in_range(); nr.advance()) {
++c;
}
std::cout << "took " << c << " steps" << std::endl;
return 0;
}
は(GCC < 4.7または-std=c++0x
)g++ -std=c++11 -O3
してコンパイルは約13.8秒で実行します私のコンピューターで。
私は範囲ベースのforループを使用するmain
機能を変更する場合:29.8秒に
for (const std::array<double, 7> & arr : nr) {
++c;
}
ランタイム増加を。 std::vector<double>
代わりのstd::array<double, N>
を使用しているとき偶然にも、この〜30秒ランタイムコンパイラを信じるために私をリードし、ほぼ元の実行時と同じであるは範囲ベースのforループにより生成されたコードをアンロールすることはできません。
元の速度を持っているし、まだループの範囲ベースを使用する方法はありますか?私は範囲ベースNumericRange
に2つのメンバ関数を変更することにより、forループで所望の速度を得ることができます
を:私が試した
bool operator !=(const NumericRange<N> & rhs) const {
return in_range();
// return ! (*this == rhs);
}
const NumericRange<N> & operator ++() {
advance();
// if (! in_range())
// _state = _upper;
return *this;
}
しかし、数値演算のために通常予想されるように、このコードはあまり私はLOを終了するために<
を使用し、動作しない!= operator
ために設計されて感じていますopではなく==
です。私は最初の範囲外の値を見つけることを考えましたが、分析的には数値誤差のために正確な答えを得られないかもしれません。
!= operator
は、コードを表示する他の人を誤解させることなく、<
と同様に動作するようにするにはどうすればよいですか?私は単にプライベートbegin()
とend()
機能を作ると思いますが、彼らは範囲ベースのforループのための公開する必要があります。
おかげであなたの助けのためにたくさん。
範囲ベースの 'for'ループで、' auto'を使わないのはなぜですか?私。 'for(auto arr:nr)'? –
@ JoachimPileborgあなたは正しいです、それは動作し、より少ないキーストロークを必要とします。できるだけ明確にしようとしていただけです(つまり、パフォーマンスの変化は、値を何度かコピーしていたためではありませんでした)。 – user
'auto'キーワードも*最も適切な*タイプを選択する必要があります。 – dirkgently