当我调用以下函数时,我正在开发的程序变慢了三倍。 如果没有被称为几百万次也不会坏。
double obterNormLarguraBanda(const std::vector<double>& v, int periodos)
{
int aa;
double maximo, minimo, valor;
std::vector<double>::const_iterator inicio;
if (v.size() < periodos)
{
inicio = v.begin();
}
else
{
inicio = v.end() - periodos;
}
maximo = *max_element(inicio, v.end(), excludeWrong);
minimo = *min_element(inicio, v.end(), excludeWrong);
return (v.back()-minimo)/(maximo - minimo);
}
bool excludeWrong(double i, double j)
{
if (i==-1 || j==-1) return false;
return i<j;
}
periodos
取值500。
还有另一种方法可以显着加快这个功能吗?
路易斯
答案 0 :(得分:3)
max_element
和min_element
都在遍历范围。
我相信一些编译器在他们的STL中有minmax_element
函数,但我不相信它在标准中。你可以写自己的。我最初把它写成一个没有模板的版本,但如果你有一个好的编译器,它应该没有区别。
尝试这样的事情(未经测试)
template <typename Iter, typename Pred>
void minmax_element(Iter begin, Iter end, Iter& min, Iter& max, const Pred& comp)
{
min = begin;
max = begin;
typedef std::iterator_traits<Iter>::value_type T;
for (++begin; begin != end; ++begin)
{
if (comp(*max, *begin))
max = begin;
else if (comp(*begin, *min))
min = begin;
}
}
template <typename Iter>
void minmax_element(Iter begin, Iter end, Iter& min, Iter& max)
{
minmax_element(begin, end, min, max, std::less<std::iterator_traits<Iter>::value_type>());
}
答案 1 :(得分:3)
与其他人所说的相反,我认为用std::max_element()
取代对std::min_element()
和minmax_element()
的两次调用会以显着的方式改善性能,因为迭代2 * n次操作1次或用2次操作迭代n次几乎没有差别。
然而,有什么不同之处在于从算法中完全消除两个调用。也就是说,找到最小和最大元素,然后在新数据进入时检查它们,而不是再次将新数据与整个容器进行比较。
double obterNormLarguraBanda(const std::vector<double>& v,
double maximo, double minimo)
{
return (v.back()-minimo)/(maximo - minimo);
}
bool excludeWrong(double i, double j)
{
if (i==-1 || j==-1) return false;
return i<j;
}
// usage example
void f()
{
std::vector<double> v;
// ...
double maximo = *max_element(inicio, v.end(), excludeWrong);
double minimo = *min_element(inicio, v.end(), excludeWrong);
for( int i = 0; i != 1000; ++i ) {
// if( ! excludeWrong(new_datum, maximo) ) maximo = new_datum;
// if( excludeWrong(new_datum, minimo) ) minimo = new_datum;
double d = obterNormLarguraBanda(...);
}
}
答案 2 :(得分:1)
您可以用一个std::minmax_element()
替换这两个电话。
答案 3 :(得分:0)
您没有解释您的代码是如何使用的,在某些情况下,您可以缓存min / max的计算,而不是在循环中执行此操作。例如,如果很少更改输入向量,则每次重新计算都没有意义。即使它发生变化,您也可以在不超过periodos
元素的情况下更新最小值/最大值(动态编程可能有所帮助)。
您还可以检查生成的程序集以检查奇怪的函数调用(例如迭代器安全检查),我知道至少MSVC 2005/2008默认情况下启用它们,即使在发布模式下也是如此(参见_SCL_SECURE宏)。
答案 4 :(得分:0)
这不是关于性能的具体问题的答案,所以也许没有价值。但似乎excludeWrong
比较函数会导致意外或可能依赖于实现的结果。如果比较的第一个值是-1
,则可以将其计算为所有情况的最小值和最大值。我使用gcc v4.0.2和Microsoft的编译器v15.00.21022.08进行了测试。例如,以下内容:
std::vector<double> v;
v.push_back( -1 );
v.push_back( 1 );
v.push_back( 2 );
cout << "min: " << *min_element( v.begin(), v.end(), excludeWrong ) << endl;
cout << "max: " << *max_element( v.begin(), v.end(), excludeWrong ) << endl;
打印:
min: -1
max: -1
也许这是理想的结果,但似乎有点奇怪。