I've profilowania wąskie gardło w moim kodu (funkcja pokazana poniżej), który jest wywoływana kilka milionów razy. Mogłabym skorzystać z porad dotyczących zwiększania wydajności. Numery XXXs
zostały pobrane z Sleepy.Optymalizacja wydajności pętli
Zestawione ze studiem wizualnym 2013, /O2
i innymi typowymi ustawieniami wydania.
indicies
zwykle zawiera od 0 do 20 wartości, a inne parametry mają ten sam rozmiar (b.size() == indicies.size() == temps.size() == temps[k].size()
).
1: double Object::gradient(const size_t j,
2: const std::vector<double>& b,
3: const std::vector<size_t>& indices,
4: const std::vector<std::vector<double>>& temps) const
5: 23.27s {
6: double sum = 0;
7: 192.16s for (size_t k : indices)
8: 32.05s if (k != j)
9: 219.53s sum += temps[k][j]*b[k];
10:
11: 320.21s return boost::math::isfinite(sum) ? sum : 0;
13: 22.86s }
Wszelkie pomysły?
Dzięki za porady facetów. Tutaj były wyniki dostałam od sugestii:
znalazłem to ciekawe, że przejście na cbegin()
i cend()
miał tak duży wpływ. Domyślam się, że kompilator nie jest tak inteligentny, jak mógłby. Cieszę się z uderzenia, ale wciąż jestem ciekawy, czy jest tu więcej miejsca przez rozwijanie lub wektoryzację.
Dla zainteresowanych tu mój punkt odniesienia dla isfinite(x)
:
boost::isfinite(x):
------------------------
SPEED: 761.164 per ms
TIME: 0.001314 ms
+/- 0.000023 ms
std::isfinite(x):
------------------------
SPEED: 266.835 per ms
TIME: 0.003748 ms
+/- 0.000065 ms
Ponieważ jest to bardzo mały fragment kodu, możesz spróbować wykonać inline. –
J nigdy się nie zmienia, więc jeśli odwrócisz wektor temps, możesz podnieść dostęp J do pętli. – user4581301
Transpozycja temps sprawi, że będzie znacznie bardziej przyjazny dla pamięci podręcznej. – tzaman