Глобальные затраты времени против суммы затрат местного времени - цикл «за» - PullRequest
0 голосов
/ 25 октября 2019

Как бы глупо это ни звучало, я хотел бы знать, могут ли быть подводные камни при попытке согласовать временные затраты для цикла for, измеряемые

  • в точках времени, находящихся за пределамицикл for ( глобальные или внешние временные затраты)
  • или, если точки времени находятся внутри цикла и кумулятивно считаются ( локальные или внутренняя стоимость времени)?

Приведенный ниже пример иллюстрирует мои трудности с получением двух равных измерений:

#include <iostream>
#include <vector> // std::vector
#include <ctime> // clock(), ..

int main(){
  clock_t clockStartLoop;
  double timeInternal(0)// the time cost of the loop, summing all time costs of commands within the "for" loop
    , timeExternal // time cost of the loop, as measured outside the boundaries of "for" loop
    ;
  std::vector<int> vecInt; // will be [0,1,..,10000] after the loop below
  clock_t costExternal(clock());
  for(int i=0;i<10000;i++){
    clockStartLoop = clock();
    vecInt.push_back(i);
    timeInternal += clock() - clockStartLoop; // incrementing internal time cost
  }
  timeInternal /= CLOCKS_PER_SEC;
  timeExternal = (clock() - costExternal)/(double)CLOCKS_PER_SEC;

  std::cout << "timeExternal = "<< timeExternal << " s ";
  std::cout << "vs timeInternal = " << timeInternal << std::endl;
  std::cout << "We have a ratio of " << timeExternal/timeInternal << " between the two.." << std::endl;
}

Я обычно получаю соотношение около 2например,

timeExternal = 0,008407 с против timeInternal = 0,004287 У нас есть отношение 1,96105 между двумя ..

, тогда как я надеялся, что отношение ближе к 1.

  • Это просто потому, что в цикле есть операции внутренние , которые не измеряются разностью clock () (такой как увеличение timeInternal)?
  • Может ли операция i++ в for(..) быть незначительной во внешнем измерении, а также объяснить разницу с внутренним?

Я на самом деле имею дело сболее сложный код, и я хотел бы изолировать временные затраты в цикле, будучи уверенным, что все временные интервалы, которые я рассматриваю, составляют полный круг (чего я до сих пор не достиг ..). Большое спасибо

1 Ответ

1 голос
/ 26 октября 2019

timeExternal = 0,008407 с против timeInternal = 0,004287 У нас есть соотношение 1,96105 между двумя ..

Ожидается соотношение ~ 2 - безусловно, самый тяжелый вызов вВаш цикл clock() (в большинстве систем clock() является системным вызовом ядра).

Представьте, что реализация clock() выглядит следующим образом псевдокод :

clock_t clock() {
    go_to_kernel(); // very long operation
    clock_t rc = query_process_clock();
    return_from_kernel(); // very long operation
    return rc;
}

Теперь, возвращаясь к циклу, мы можем комментировать места, где тратится время:

  for(int i=0;i<10000;i++){
    // go_to_kernel - very long operation
    clockStartLoop = clock();
    // return_from_kernel - very long operation
    vecInt.push_back(i);
    // go_to_kernel - very long operation
    timeInternal += clock() - clockStartLoop;
    // return_from_kernel - very long operation
  }

Таким образом, между двумя вызовами на clock() у нас есть 2 длинные операции с общим количеством вцикл 4. Следовательно, отношение 2 к 1.

  • Это только потому, что существуют операции внутри цикла, которые не измеряются разницей clock() (такойкак увеличение timeInternal)?

Нет, увеличение timeInterval незначительно.

  • Может ли операция i++ в for(..) быть не пренебрежимо малым во внешнем измерении, а также объяснить разницу с внутренним измерением?

Нет, i++ также незначительно. Удалите внутренние вызовы на clock(), и вы увидите намного более быстрое время выполнения. В моей системе это было 0,00003 с.

Следующая самая дорогая операция после clock() - vector::push_back(), потому что ей нужно изменить размер vector. Это амортизируется квадратичным фактором роста и может быть полностью устранено путем вызова vector::reserve() перед входом в цикл.

Вывод: при тестировании обязательно синхронизируйте целые циклы, а не отдельные итерации. А еще лучше - использовать фреймворки, такие как Google Benchmark , которые помогут избежать многих других ловушек (например, оптимизации компилятора). Также есть quick-bench.com для простых случаев (на основе Google Benchmark).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...