Потихоньку учусь использовать алгоритмы стандартной библиотеки C++. Самодокументирование кода - это хорошо, но решил проверить и производительность. Например, std::accumulate. Qt Creator, mingw, windows, QTest. В объекте создаём приватные поля:
QVector
В конструкторе пишем:
std::fill(arr_,arr_+size_,1.0);
Создаём три слота:
void Tester::benchmarkSimpleLoopOverArray()
{
sum_=0;
QBENCHMARK
{
for (size_t i=0;i
RESULT : Tester::benchmarkSimpleLoopOverArray():
0.061 msecs per iteration (total: 63, iterations: 1024)
PASS : Tester::benchmarkSimpleLoopOverArray()
RESULT : Tester::benchmarkSmartLoopOverArray():
0.0000046 msecs per iteration (total: 78, iterations: 16777216)
PASS : Tester::benchmarkSmartLoopOverArray()
RESULT : Tester::benchmarkAccumulateOverArray():
0.0532 msecs per iteration (total: 109, iterations: 2048)
PASS : Tester::benchmarkAccumulateOverArray()
На арифметике указателей получаем выигрыш на 4 порядка! Ради такого я готов написать пару лишних строк кода и строчку комментария.
Соответственно, вопросы:
Можно ли как-то улучшить производительность алгоритмов, как мы это сделали с обычным циклом? Я пробовал генерить два таких же указателя для начала и конца массива, результат получается хуже - таким же, как у наивного цикла.
Может ли кто-нибудь проверить, сохранится ли такое соотношение результата под другими компиляторами/операционками?
Ну и самый главный вопрос. Как получился такой огромный выигрыш у "хитрого" цикла? Я не настолько хорошо знаю ассемблер, чтобы залезть в код и посмотреть отличия, но получается, что в наивном цикле и стандартных алгоритмах используется какая-то очень тяжёлая операция, которой нет во втором примере. Какая?
Upd: спасибо zenden2k, проблема действительно была в том, что указатели я выставлял до входа в цикл. В результате второй тест полноценно выполнялся только один раз, а потом на входе в for проверял условие
pf
Ответ
У вас ошибка в коде.
Вот это
float * pf=arr_;
float * pf0=pf+size_;
должно быть внутри QBENCHMARK а не снаружи.
Также тесты у вас не равнозначны, потому что используется общая переменная sum_, она принимает разные значения в зависимости от кол-ва итераций.
Ее надо инициализировать внутри QBENCHMARK
float sum_ = 0;
Тогда получите приблизительно одинаковые результаты
RESULT : TestClass::benchmarkSmartLoopOverArray():
0.058 msecs per iteration (total: 60, iterations: 1024)
PASS : TestClass::benchmarkSimpleLoopOverArray()
RESULT : TestClass::benchmarkSimpleLoopOverArray():
0.059 msecs per iteration (total: 61, iterations: 1024)
PASS : TestClass::benchmarkAccumulateOverArray()
RESULT : TestClass::benchmarkAccumulateOverArray():
0.059 msecs per iteration (total: 61, iterations: 1024)
PASS : TestClass::cleanupTestCase()
Totals: 5 passed, 0 failed, 0 skipped, 0 blacklisted
********* Finished testing of TestClass *********
Комментариев нет:
Отправить комментарий