clock () против getsystemtime () - PullRequest
       19

clock () против getsystemtime ()

0 голосов
/ 22 декабря 2010

Я разработал класс для расчетов по многопоточности, и только один экземпляр этого класса используется потоком. Также я хочу измерить продолжительность вычислений, перебирая контейнер этого класса из другого потока. Приложение win32. Дело в том, что я прочитал QueryPerformanceCounter, который полезен при сравнении измерений в одном потоке. Поскольку я не могу использовать это моя проблема, я думаю о clock () или GetSystemTime (). Печально, что оба метода имеют «разрешение» в миллисекундах (поскольку CLOCKS_PER_SEC равно 1000 на win32). Какой метод я должен использовать или обобщить, есть ли лучший вариант для меня? Как правило, я должен проводить измерения вне рабочего потока. Вот пример кода.

unsinged long GetCounter()
{
  SYSTEMTIME ww;
  GetSystemTime(&ww);
  return ww.wMilliseconds + 1000 * ww.wSeconds; 
// or
  return clock();
}

class WorkClass
{
  bool is_working;
  unsigned long counter;
  HANDLE threadHandle;
public:
  DoWork()
  {
    threadHandle = GetCurrentThread();
    is_working = true;
    counter = GetCounter();
    // Do some work
    is_working = false;
  }
};

void CheckDurations() // will work on another thread;
{
  for(size_t i =0;i < vector_of_workClass.size(); ++i)
  {
    WorkClass & wc = vector_of_workClass[i];
    if(wc.is_working)
    {
      unsigned long dur = GetCounter() - wc.counter;
      ReportDuration(wc,dur);
      if( dur > someLimitValue)
        TerminateThread(wc.threadHandle);
    }
  }
}

Ответы [ 4 ]

3 голосов
/ 22 декабря 2010

QueryPerformanceCounter отлично подходит для многопоточных приложений.Инструкция процессора о том, что может использоваться (rdtsc), потенциально может давать недопустимые результаты при вызове на разных процессорах.

Я рекомендую прочитать "Game Timing and Multicore Processors" .

В вашем конкретном приложении проблема, которую вы пытаетесь решить, заключается в использовании тайм-аута в некоторых потенциально долго работающих потоках.Правильным решением этой проблемы будет использование функции WaitForMultipleObjects со значением времени ожидания.Если время истекает, вы можете прервать все потоки, которые все еще работают - в идеале, установив флаг, который проверяет каждый поток, но TerminateThread может подойти.

1 голос
/ 22 декабря 2010

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

1 голос
/ 22 декабря 2010

оба метода имеют точность в миллисекундах

Они не имеют.У них разрешение миллисекунды, точность гораздо хуже.Большинство машин увеличивают значение только с интервалами 15,625 мсек.Это чертовски много циклов ЦП, обычно недостаточно хороших, чтобы получить какой-либо надежный показатель эффективности кода.

QPF работает намного лучше, не знаю, почему вы не можете его использовать.Профилировщик - это стандартный инструмент для измерения эффективности кода.Ударяет зависимость, которую вы не хотите.

0 голосов
/ 22 декабря 2010

GetSystemTime получает абсолютное время, часы - относительное время, но оба измеряют прошедшее время, а не процессорное время, связанное с фактическим потоком / процессом.

Конечно, clock () более переносим.Сказав, что я использую clock_gettime в Linux, потому что с этим вызовом я могу получить как истекшее, так и потоковое процессорное время.

boost имеет некоторые функции времени, которые вы можете использовать, которые будут работать на нескольких платформах, если вы хотите независимый от платформы код.

...