суббота, 15 сентября 2012 г.

Производительность NXT блока

Раз уже в прошлой заметке зашла речь о проекте RWTH - Mindstorms NXT Toolbox for MATLAB, то следует рассказать об одном интересном исследовании проведенном в рамках этого проекта.
Начать следует с того, что этот проект выкладывает все свои наработки (исходные коды) в свободный доступ, т.е. каждый может пройтись по дереву исходников и ознакомиться с наиболее интересными. Так вот, среди множества файлов есть группа под общим название Performance Сheck (Проверка производительности), которые предоставляют немного новой информации о том, как работает программное обеспечение NXT блока.

На самом деле автор данных материалов делал исследование с целью измерить какие трюки, уловки он смог бы применять в своих программах на языке Not eXactly C, чтобы его роботы были более быстрыми, имели меньшее время реакции на события и т.п. Для этого он создал набор тестов. измеряющие производительность стандартного NXT firmware.

Эти тесты включали в себя следующие проверки:

  • сколько выполняются математические операции умножение и сложение, как для данных типа int, так и для long
  • преимущество битовых сдвигов (только для расширенной версии FW, поставляемой с NXC), тоже для отдельно для int и long
  • как быстро работает пустой цикл (ну т.е. в нем все равно будут операции инкремента и сравнения)
  • сколько занимают вызовы стандартных функций CurrentTick() и MotorTachoCount()
  • насколько быстр вычисление позиции элемента в одномерных массивах
  • имеет ли смысл использовать inline ассемблерный код, вместо использования стандартной операции инкремента (++)

Итак, в ходе экспериментов выяснилось:
  • нет никакого выигрыша в производительности между использованием типов данных int и long
  • в течении секунды выполняется примерно 5200 операций сложения или умножения. Причем, с точки зрения производительности одна операция умножения занимает практически столько же сколько операция сложения! Для людей знающих, как выполняются двоичные операции на процессоре, это будет довольно интересный и заслуживающий внимания факт. Автор делает предположение, что это может быть из-за внутреннего ограничения выполняемого NXT firmware, определяющего сколько процессорных "тиков" может использовать каждая задача.
  • операции битовых сдвигов (<< >>) медленнее больше, чем в два раза, других операций. Не используйте сдвигов - замените их арифметическими операциями: x*2^n - для левых сдвигов, x/2^n - для правых (естественно, 2^n лучше сразу рассчитать и значение вставить в код).
  • пустой цикл не выполняется быстрее
  • вычисление позиции элемента в массиве соизмеримо по скорости с математическими операциями
  • ассемблерная inline вставка для выполнения инкремента по производительности абсолютно равна операции ++
  • подтвердилось ожидание того, что увеличение количества параллельных выполняющихся задач уменьшает производительность остальных. Т.е. если мы стартуем какую-то дополнительную задачу помимо main, то процессору нужно теперь тратить время на работу обеих задач, а значит производительность основной задачи упадет в два раза.
  • функция Wait() не помогает значительно освобождать ресурсы процессора. Иными словами, если в дополнительной задаче сделать задержку в 100 миллисекунд, т.е. задача будет выполнятся всего 10 раз в секунду, то это не приведет к росту производительности основной задачи - она также будет в два раза медленнее. Похоже внутренняя реализация операции Wait() по прежнему тратит время на вычисление, а не прошли ли это 100 мс. В то время как в "настоящих" операционных системах, ядро ОС ответственно за уведомление задачи, что "время сна" закончилось.

В общем, очень интересные получились результаты, позволяющие на некоторые вещи в программировании LEGO роботов взглянуть c новой стороны.

Также данный NXC-файл будет полезен тем, кто только изучает язык Not eXactly C, чтобы почерпнуть из него много новой информации, полезной в будущем.

А кто-нибудь сможет провести аналогичные эксперименты на Robolab, leJOS и RobotC? У них ведь свои собственные firmware - как ведут они себя с точки зрения производительности.

3 комментария:

  1. Думаю, у языков со своими firmware результаты буду совсем другие. Не случайно количество тиков в пустом цикле в RobotC точно больше 5200 (сам измерял).

    ОтветитьУдалить
    Ответы
    1. На самом деле все еще интереснее. Я взял свой блок (NXT2.0 std FW 1.31), скомпилировал PerformanceChk2.nxc, результаты которого представлены в этой статье и получил, что скорость работы на самом деле больше, чем в два раза больше - 12000 матем. операций против 5200, заявленных в прошлом.

      Удалить
  2. Анонимный26 июня 2013 г., 2:43

    10000 циклов пустых на robotC требуют лишь 129 миллисекунд, если переменную заменить на тип лонг то уже 169 миллисекунд, а если переменную цикла заменить на флоат то уже 209)

    ОтветитьУдалить

Related Posts Plugin for WordPress, Blogger...