Geschwindigkeit von STL numerics
-
Hallo,
ich habe zwei Funktionen verglichen, die mir den Korrelationskoeffizienten zweier Zahlenlisten berechnen. Die eine benutzt STL-Funktionen, die andere berechnet die benoetigten Summen "von Hand". Bei einer Listenlaenge von je 1000000 double's:x
benoetigt die STL-Version 130000 clock ticks waehrend die "von Hand" Version nur 70000 benoetigt (kompiliert mit g++ -O2 -march=k6 test.cpp).Kann mir jemand erklaeren, woran das liegt? Ich haette erwartet, dass die STL vergleichbar, wenn nicht gar schneller waere. Hier der Code:
#include <iostream> #include <numeric> #include <cmath> #include <vector> #include <time.h> // compare two versions of calculating correlation coefficients // using STL functions template <typename T> T CC_stl(const std::vector<T>& l1, const std::vector<T>& l2) { T corr_coefficient; T sum1, sum1_sq, sum2, sum2_sq, sum12; T nominator; T denominator; int list_size = l1.size(); sum1 = std::accumulate(l1.begin(), l1.end(), 0.0); sum2 = std::accumulate(l2.begin(), l2.end(), 0.0); sum1_sq = std::inner_product(l1.begin(), l1.end(), l1.begin(), 0.0); sum2_sq = std::inner_product(l2.begin(), l2.end(), l2.begin(), 0.0); sum12 = std::inner_product(l1.begin(), l1.end(), l2.begin(), 0.0); nominator = sum12 - sum1*sum2/list_size; denominator = (sum1_sq - sum1*sum1/list_size) * (sum2_sq - sum2*sum2/list_size); corr_coefficient = nominator / std::sqrt(denominator); return corr_coefficient; } // manual calculation template <typename T> T CC(const std::vector<T>& l1, const std::vector<T>& l2) { T corr_coefficient; T sum1, sum1_sq, sum2, sum2_sq, sum12; T nominator; T denominator; sum1 = sum2 = sum1_sq = sum2_sq = sum12 = 0; int list_size = l1.size(); for ( int i = 0; i < list_size; i++) { sum1 += l1[i]; sum2 += l2[i]; sum1_sq += l1[i]*l1[i]; sum2_sq += l2[i]*l2[i]; sum12 += l1[i]*l2[i]; } nominator = sum12 - 1.0*sum1/list_size * sum2; denominator = (sum1_sq - 1.0/list_size * sum1*sum1) * (sum2_sq - 1.0/list_size * sum2*sum2); corr_coefficient = nominator / std::sqrt(denominator); return corr_coefficient; } int main() { const unsigned int points = 1000000; std::vector<double> l1(points), l2(points); clock_t stl0, stl1, std0, std1; // populate both vectors with numbers for ( int i = 0; i < points; i++) { l1[i] = std::sqrt(1.0*i); l2[i] = 1.0/(i+1); } stl0 = clock(); double cc_stl = CC_stl(l1, l2); stl1 = clock(); std0 = clock(); double cc_std = CC(l1, l2); std1 = clock(); std::cout << " STL Version: " << cc_stl << " clocks: " << stl1 - stl0 << '\n' << " Normal Version: " << cc_std << " clocks: " << std1 - std0 << '\n'; return 0; }Vielen Dank,
Tim
-
Bei der handgeschriebenen Variante machst du ja alles in einer Schleife und in der STL müssen ja 5 mal der ganze Vektor durchlaufen werden?!
-
ich hab mal den source genommen und bei mir kompiliert, folgende ergebnisse:
STL Version: -0.0251371 clocks: 234
Normal Version: -0.0251371 clocks: 282STL Version: -0.0251371 clocks: 250
Normal Version: -0.0251371 clocks: 266STL Version: -0.0251371 clocks: 234
Normal Version: -0.0251371 clocks: 282STL Version: -0.0251371 clocks: 234
Normal Version: -0.0251371 clocks: 266STL Version: -0.0251371 clocks: 234
Normal Version: -0.0251371 clocks: 282STL Version: -0.0251371 clocks: 250
Normal Version: -0.0251371 clocks: 266STL Version: -0.0251371 clocks: 250
Normal Version: -0.0251371 clocks: 266STL Version: -0.0251371 clocks: 234
Normal Version: -0.0251371 clocks: 282STL Version: -0.0251371 clocks: 235
Normal Version: -0.0251371 clocks: 281bei mir ist die "handmade" also bissl langsamer.
habs einfach mit dem aktuellen dev-cpp und standard compiler-einstellungen kompiliert.