Как запустить цикл с определенной скоростью в C (в эмуляции)

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

Мне было интересно, есть ли какой-нибудь способ, в C, вызвать функцию на некотором заданном интервале (в МГц). Для контекста я пишу это на Mac, так что все, что POSIX или OS X SDK будет работать (я просматривал libdispatch, но ничего не видел).

Будет ли лучше просто запустить цикл и вычислить дельту времени с момента последнего цикла? Это кажется довольно неэффективным (также здесь может стать вытеснение). Каковы будут другие способы сделать это? Спасибо.

1
задан 19.01.2019, 18:04

4 ответа

Использование clock_gettime() и nanosleep() - путь. Какой-то другой механизм, вызывающий вашу функцию периодически, будет определенно медленнее. Вы можете даже рассмотреть циклы и счетчики циклов вместо использования nanosleep(). Рассмотрим некоторые цифры:

При частоте 1 МГц ваша функция должна работать 1 микросекунду. На частоте 10 МГц ваша функция должна работать 100 наносекунд.

Некоторые экспериментальные данные о времени системных вызовов и переключениях контекста: https://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html [ 113]

Так что это выглядит как более 50 наносекунд для системного вызова и более микросекунды для переключения контекста. Некоторые другие вещи, вызывающие вашу функцию, помимо вашего собственного кода в том же процессе, вероятно, займут «слишком много времени».

0
ответ дан 07.04.2019, 13:59
  • 1
    К вашему сведению: macOS clock_gettime() имеет разрешение одной микросекунды (см. clock_getres()). Таким образом, для частот, больше, чем 1 МГц, Вы can' t действительно используют те средства — или поведение, которое Вы получаете, будет ошибочно. – Jonathan Leffler 19.01.2019, 20:16
  • 2
    Если OP готов взять международные маркировки не строки, мы могли бы векторизовать это, я думаю. I' m, просто пытаясь завершить идею – roganjosh 26.01.2019, 05:22

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

Так что, может быть, вы могли бы использовать другой подход: не полагайтесь на время вашей системы, но используйте также эмулированное время.

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

Будет ли одна конкретная функция быстрее, чем в реальной жизни? Не имеет значения, ваша система будет знать, что XX тиков прошло, и выполнит любые прерывания или что-нибудь на этом основании.

При таком подходе реальная секунда не будет равна симулированной секунде, но ваша эмуляция будет всегда одинаковой, независимо от других приложений или проблем системного планирования.

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

Наконец, взгляните на этот вопрос , так как они дают много информации об эмуляции, которую стоит прочитать. В частности, мой описанный выше подход будет соответствовать подходу «интерпретации», описанному по этой ссылке.

0
ответ дан 07.04.2019, 13:59
  • 1
    Я попробовал код, но он возвращает ту же ошибку, которая получила меня, когда я попробовал @yatu' s код ValueError: Bin edges must be unique: array([ 0., 0., 5., 26.]). You can drop duplicate edges by setting the 'duplicates' kwarg – CASA_DE_BS 26.01.2019, 06:55

Это будет трудно получить точную, потому что OS X не является системой реального времени. Если абсолютная точность не требуется, я бы использовал интервальный таймер, который истекает каждые 1/n, например, со скоростью «n в секунду», а затем выполните tick в обработчике срока действия.

Отправной точкой будет POSIX setitimer() и вызов tick в обработчике сигналов

0
ответ дан 07.04.2019, 13:59
  • 1
    Корма А-ч, я видел for цикл, и считайте его неправильный путь! Я шел для np.digitize. You' ре корректный AFAIK. – roganjosh 26.01.2019, 05:24

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

Время переключения контекста и задержка не будут основными проблемами здесь.

Если вы эмулируете поведение целевой системы, вам нужно также связать время выполнения инструкций целевой системы и во время выполнения эмулятора (в соответствии с текущим прошедшим временем) изменить скорость, с которой эмулируются целевые инструкции

0
ответ дан 07.04.2019, 13:59
  • 1
    Платформа является набором кода плюс ресурсы. Должно быть возможно добавить mlmodel к платформе, но если Вы тогда посмотрите в файле платформы (с Выставочным Содержанием Пакета) тогда, то mlmodelc папка будет явно видима. Таким образом, это только безопасно если Ваш разработчик doesn' t знают, как посмотреть в платформах.;-), Но действительно, этот doesn' t походят на здоровые рабочие отношения. – Matthijs Hollemans 27.01.2019, 01:42

Теги

Похожие вопросы