Вот краткий вариант вашего кода:
#include <chrono>
#include <iostream>
int main()
{
auto tOuterBeg = std::chrono::high_resolution_clock::now();
auto timeSum = 0ul;
for (int i = 0 ; i < 10000 ;++i) {
auto tInnerBeg = std::chrono::high_resolution_clock::now();
auto tInnerEnd = std::chrono::high_resolution_clock::now();
timeSum += std::chrono::duration_cast<std::chrono::milliseconds>(tInnerEnd - tInnerBeg).count();
}
auto tOuterEnd = std::chrono::high_resolution_clock::now();
auto outerDur = std::chrono::duration_cast<std::chrono::milliseconds>(tOuterEnd - tOuterBeg).count();
std::cout << "inner: " << timeSum << " outer: " << outerDur << "\n";
}
На wandbox с GCC (8.2.0 с -O2) это печатает:
inner: 0 outer: 26
Но эта огромная разницатолько потому, что миллисекунды слишком грубы для синхронизации цикла.С chrono::microseconds
дела обстоят лучше:
inner: 10462 outer: 23960
Это все еще не хорошо, но все же намного лучше, чем раньше.Далее, факт, что в каждой итерации есть два вызова high_resolution_clock::now()
.timeSum
раз только один из вызовов now()
, но outerDur
учитывает оба.Это объясняет, почему outer
отображает примерно вдвое больше inner
.
Если вы измените цикл на вызов high_resolution_clock::now()
только один раз за итерацию, тогда разница между outerDur
и timeSum
будетбыть намного меньше:
auto tInnerBeg = std::chrono::high_resolution_clock::now();
for (int i = 0 ; i < 10000 ;++i) {
auto tInnerEnd = std::chrono::high_resolution_clock::now();
timeSum += std::chrono::duration_cast<std::chrono::microseconds>(tInnerEnd - tInnerBeg).count();
tInnerBeg = tInnerEnd;
}
Результат этого намного ближе к тому, что вы ожидаете:
inner: 10817 outer: 12912
Разницу можно еще больше устранить, перейдя на наносекунды.Кажется, что округление микросекунд приводит к слишком большим ошибкам:
inner: 13612956 outer: 13614153
Небольшая разница обусловлена стоимостью duration_cast
и самой петлей.
В целом, кажется, что намашина wandbox, один звонок на std::chrono::high_resolution_clock::now()
занимает 1,361 мкс.Примите это во внимание.
РЕДАКТИРОВАТЬ
Видя редактирование вопроса, я должен согласиться с Робертом Анджеюком, что для небольшого числа итераций, равного 4, проблема, вероятно, связана с временем, проведенным в деструкторах,Для подсчета в деструкторах вы можете собрать время после запуска деструкторов, поместив код в отдельный и внутренний блок {}
:
auto tInnerBeg = std::chrono::high_resolution_clock::now();
for (int i = 0 ; i < 10000 ;++i) {
{
////////////////////////
// the timed code goes here
//////////////////////////
}
auto tInnerEnd = std::chrono::high_resolution_clock::now();
timeSum += std::chrono::duration_cast<std::chrono::microseconds>(tInnerEnd - tInnerBeg).count();
tInnerBeg = tInnerEnd;
}