Изменение синхронизации часов на разных компьютерах

#c #c 17 #timing #chrono #gameboy

#c #c 17 #синхронизация #c -хроно #gameboy

Вопрос:

Я работаю над реализацией DMG-01 (A.K.A gameboy 1989) на моем github. Я уже внедрил как APU, так и PPU, с (почти) идеальной синхронизацией на моем ПК (и ПК моих друзей). Однако, когда я запускаю эмулятор на одном из компьютеров моего друга, он работает в два раза быстрее, чем у меня или у остальных моих друзей.

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

Часы.Файл заголовка h:

 class Clock
{
// ...
public:
    void SyncClock();

private:
    /* API::LR35902_HZ_CLOCK is 4'194'304 */
    using lr35902_clock_period = std::chrono::duration<int64_t, std::ratio<1, API::LR35902_HZ_CLOCK>>;
    static constexpr lr35902_clock_period one_clock_period{1};
    using clock = std::chrono::high_resolution_clock;

private:
    decltype(clock::now()) _last_tick{std::chrono::time_point_cast<clock::duration>(clock::now()   one_clock_period)};
};
  

Clock.cpp файл

 void Clock::SyncClock()
{
    // Sleep until one tick has passed.
    std::this_thread::sleep_until(this->_last_tick);

    // Use time_point_cast to convert (via truncation towards zero) back to
    // the "native" duration of high_resolution_clock
    this->_last_tick = std::chrono::time_point_cast<clock::duration>(this->_last_tick   one_clock_period);
}
  

Который вызывается в main.cpp вот так:

 int main()
{
    // ...
    while (true)
    {
        // processor.Clock() returns the number of clocks it took for the processor to run the
        // current instruction. We need to sleep this thread for each clock passed.
        for (std::size_t current_clock = processor.Clock(); current_clock > 0; --current_clock)
        {
            clock.SyncClock();
        }
    }
    // ...
}
  

Есть ли причина, по которой chrono в этом случае будет по-другому влиять на другие компьютеры? Время является абсолютным, я бы понял, почему на одном ПК запуск эмулятора будет медленнее, но почему быстрее?
Я проверил тип моих часов (high_resolution_clock), но я не понимаю, почему это так.
Спасибо!

Комментарии:

1. Если вы проверите period тип std::high_resolution_clock , отличается ли он между двумя системами?

2. @Someprogrammerdude Мой друг не очень программист, поэтому мне придется установить visual studio на его ПК (если он согласен, но), но в любом случае я не вижу причины, по которой std ::ratio изменится между двумя системами (стандарт также не определяет такую разницу)

3. Один из вас запускает гиперпоточность, а другой нет?

4.Вам не нужно устанавливать Visual Studio, просто добавьте ведение std::ratio num den журнала элементов и в вашу программу.

5. @Someprogrammerdude Хорошая идея, я попробую и обновлю ее здесь.

Ответ №1:

Я думаю, вы можете столкнуться с переполнением под капотом <chrono> .

Выражение:

 clock::now()   one_clock_period
  

является проблематичным. clock есть high_resolution_clock , и обычно это имеет nanoseconds разрешение. one_clock_period имеет единицы измерения 1/4'194'304 . Результирующим выражением будет a time_point с a period of 1/8'192'000'000'000 .

При использовании 64-разрядных интегральных типов max() со знаком такая точность составляет чуть более 13 дней. Поэтому, если clock::now() возвращает .time_since_epoch() значение, превышающее 13 дней, _last_tick оно будет переполняться и может иногда быть отрицательным (в зависимости от того, сколько clock::now() превышает 13 дней).

Чтобы исправить, попробуйте выполнить приведение one_clock_period к точности clock немедленно:

 static constexpr clock::duration one_clock_period{
    std::chrono::duration_cast<clock::duration>(lr35902_clock_period{1})};