Этот пример иллюстрирует, как использовать в своих интересах выполнение многопоточного кода на многоядерном процессоре с помощью графического разделения. Этот пример требует, чтобы Simulink® Coder™ сгенерировал многопоточный код.
Одна цель модельно-ориентированного проектирования состоит в том, чтобы создать реалистические модели физических систем и симулировать эти модели в режиме реального времени, например, проверять контроллеры, использующие оборудование в цикле (HIL). Однако, когда больше опций добавляется к модели объекта управления, вычислительные требования могут превысить ресурсы, доступные одножильными системами обработки.
Разделение объекта и контроллера в отдельные части является одним способом обратиться к вычислительным потребностям сложных моделей. С Simulink® можно разделить объект с помощью блоков Model и затем присвоить код, сгенерированный каждой подмоделью к потокам для выполнения в реальном времени в системе HIL, таким как Simulink Real-Time™. Чтобы видеть, как это работает, давайте использовать наш хост - компьютер в качестве заместителя для среды выполнения в реальном времени и сгенерируем многопоточный код в реальном времени для следующей модели.
slexMulticoreSolverExample
Рисунок выше показов, что код, сгенерированный для модели, разделен на два потока. В этом примере цель принята, чтобы быть Симметричным Многоядерным процессором, так, чтобы потоки не были сопоставлены ни с каким конкретным ядром. Операционная система ответственна за использование лучше всего ядер при планировании выполнения потока. Идеально, чтобы обеспечить максимальную гибкость, количество потоков (Nt) должно быть больше количества ядер (Nc). Дважды кликните на кнопке 'Generate Code and Profile Report', чтобы сгенерировать многопоточный код, профилировать его выполнение и визуализировать результаты. Визуализация показывает базовую карту заполнения того, как ядра использовались на каждом временном шаге выполнения. Это видно, который потоки пускают в ход через ядра, как считается лучше всего планировщиком операционной системы. Этот вид планирования хорош, когда операционная система также должна запустить другие процессы.
Simulink® Coder™ генерирует код, таким образом, что два потока могут выполниться одновременно и возможно на двух различных ядрах. Это означает, что значения сигналов для и должны синхронизироваться между двумя потоками. Simulink® предоставляет несколько возможностей обрабатывать это требование, как проиллюстрировано здесь:
Используя скрипт ниже, мы симулируем и продемонстрируем эффект детерминированных режимов изучить, как Simulink® обрабатывает синхронизацию.
Контрольный раствор (ode3) - Simulink® сконфигурирован, чтобы предоставить контрольное решение путем синхронизации данных на каждом главном и незначительном временном шаге.
Нулевой Порядок Содержит - Каждый поток решает подсистему уравнений с помощью ее собственного решателя при синхронизации данных только по главным временным шагам.
Линейная экстраполяция - В дополнение к режиму Zero Order Hold, каждый решатель экстраполирует данные с помощью линейных предсказаний, чтобы компенсировать ошибки задержки данных.
Для большинства систем, где точки синхронизации являются гладкими, линейный режим экстраполяции обеспечивает хороший компромисс между коммуникационными узкими местами и числовой точностью.
h = figure; hVal = ishold; hold on; mdl = 'slexMulticoreSolverExample'; dt = get_param(mdl, 'DataTransfer'); modes = { ... 'Ensure deterministic transfer (minimum delay)', ... 'None', 'k:', ... 'Ensure deterministic transfer (maximum delay)', ... 'Zero Order Hold', 'm', ... 'Ensure deterministic transfer (maximum delay)', ... 'Linear', 'b' ... }; for i=1:3:length(modes) dt.DefaultTransitionBetweenContTasks = modes{i}; dt.DefaultExtrapolationMethodBetweenContTasks = modes{i+1}; out = sim(mdl); plot(out.logsout.get('x1').Values.Time, ... out.logsout.get('x1').Values.Data, ... modes{i+2}); end legend('Reference solution (ode3)', ... 'Zero Order Hold Extrapolation', ... 'Linear Extrapolation');
close_system('slexMulticoreSolverExample',0); close_system('slexMulticoreSolverMdlref',0); if ~hVal, hold off; end delete(h);