Многожильная симуляция и генерация кода областей потока данных

Симуляция областей потока данных

Симуляция областей потока данных в Нормальном и Режимах Accelerator усиливает многожильную архитектуру ЦП хоста - компьютера. Это автоматически делит вашу модель и моделирует подсистему с помощью нескольких потоков.

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

Генерация кода областей потока данных

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

Типы параллелизма

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

Параллелизм задачи

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

Рассмотрите систему, которая включает четыре функции. Функции, которые F2a () и F2b () параллельно, то есть, они могут запуститься одновременно. В параллелизме задачи можно разделить вычисление на две задачи. Функциональный F2b () работает на отдельном процессорном узле после того, как это получает данные Out1 от Задачи 1, и это выводит назад к F3 () в Задаче 1.

Данные показывают схему синхронизации для этого параллелизма. Задача 2 не запускается, пока это не получает данные Out1 от Задачи 1. Следовательно, эти задачи не запускаются полностью параллельно. Время, потраченное на цикл процессора, известный как время цикла,

t = tF1 + макс. (tF2a, tF2b) + tF3.

Образцовое конвейерное выполнение (конвейеризация)

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

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

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

t = макс. (Task1, Task2, Task3) = макс. (tF1, tF2a, tF2b, tF3).

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

Разворачивание

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

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

Улучшите пропускную способность симуляции с многожильной симуляцией

Этот пример показывает, как улучшить пропускную способность симуляции системы путем симуляции подсистемы с несколькими потоками. Чтобы включить автоматическое разделение системы и многопоточную симуляцию в Нормальном или Режимах Accelerator, установите Domain подсистемы к Dataflow. Для получения дополнительной информации об областях потока данных смотрите Область Потока данных

  1. Чтобы начаться, откройте модель.

    addpath (fullfile(docroot, 'toolbox', 'dsp', 'examples'));
    ex_staple_counting
  2. Моделируйте модель и наблюдайте частоту кадров системы в блоке Frame Rate Display. Этот номер указывает на количество кадров в секунду, которые Simulink® может обработать в стандартной симуляции.

  3. Чтобы включить многопоточную симуляцию и улучшить пропускную способность симуляции, установите область подсистемы к потоку данных.

    Если Property Inspector не видим, выберите View> Property Inspector.

    С выбранной подсистемой, во вкладке Execution Property Inspector, выбирают Set execution domain. Установите Domain на Dataflow.

  4. Иногда, можно увеличить доступный параллелизм в системе путем добавления Latency в систему. Чтобы выбрать оптимальное значение задержки, используйте Ассистент Симуляции Потока данных. Нажмите кнопку Dataflow assistant, чтобы открыть Ассистент Симуляции Потока данных.

  5. В Ассистенте Симуляции Потока данных нажмите кнопку Analyze. Ассистент Симуляции Потока данных анализирует подсистему для производительности симуляции и предлагает оптимальную задержку для вашей Подсистемы Потока данных.

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

  6. Нажмите кнопку Accept, чтобы применить предложенную задержку к системе. Ассистент Симуляции Потока данных применяет задержку к модели и указывает на количество потоков, которые модель будет использовать во время последующих симуляций. Задержка системы обозначается со значком задержки на образцовом холсте при выводе подсистемы.

  7. Моделируйте модель снова. Наблюдайте улучшенную пропускную способность симуляции от многопоточной симуляции в блоке Frame Rate Display.

Сгенерируйте многожильный код от подсистемы потока данных

Сконфигурируйте свою модель для многожильной генерации кода

Генерация кода требует Simulink Coder™ или лицензии Embedded Coder®. Поддерживаются одножильные и многожильные цели.

Код, сгенерированный для одножильных целей, генерирует невиртуальный код подсистемы.

Чтобы сгенерировать многожильный код, необходимо сконфигурировать модель для параллельного выполнения. Если вы не сконфигурируете свою модель для параллельного выполнения, сгенерированный код будет одним, распараллелил.

  1. В Configuration Parameters> Solver> Solver selection, выберите Fixed-step для Type и auto (Automatic solver selection) для Solver.

  2. Установите флажок Allow tasks to execute concurrently on target в панели Solver под Solver details. Установка этого флажка является дополнительной для моделей, на которые ссылаются в иерархии модели. Когда вы выбираете эту опцию для модели, на которую ссылаются, Simulink позволяет каждому уровню в модели, на которую ссылаются, выполняться как независимая параллельная задача на целевом процессоре.

  3. В Configuration Parameters> Code Generation> Interface> Advanced parameters, снимите флажок MAT-file logging.

  4. Нажмите Apply, чтобы применить настройки к модели.

Сгенерируйте многожильный код

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

Сгенерированный код C содержит одну функцию void(void) для каждой задачи или потока, созданного подсистемой потока данных. Каждая из этих функций состоит из:

  • Код С, соответствующий блокам, которые были разделены в тот поток

  • Код, который сгенерирован, чтобы обработать, как данные передаются между потоками.

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

Следующие многожильные цели поддерживаются для генерации кода.

  • Linux®, Windows® и цели рабочего стола Mac OS с помощью ert.tlc и grt.tlc.

  • Simulink Real-Time™ с помощью slrt.tlc.

  • Цели Embedded Coder с помощью Linux и операционных систем VxWorks®.

Код, сгенерированный для grt.tlc и целей рабочего стола ert.tlc, является многопоточным OpenMP использования в подсистеме потока данных. Код, сгенерированный для целей Embedded Coder, является многопоточными потоками POSIX использования.

Если ваша система содержит блоки, которые не поддерживают многопоточное выполнение, сгенерированный код является однопоточным.

Чтобы создать модель и сгенерировать код, нажмите Ctrl+B.

В сгенерированном коде можно наблюдать вызовы API поточной обработки и конвейерных задержек, которые были вставлены в модель, чтобы создать больше параллелизма.

Следующий пример показывает, что существует две функции потока, сгенерированные подсистемой потока данных, ex_staple_counting_ThreadFcn0 и ex_staple_counting_ThreadFcn1, которые выполняются с помощью разделов OpenMP. Эти функции являются частью функции dataflow_subsystem_output/step().

static void ex_staple_counting_ThreadFcn0(void)
 	{
 	  ...

	  if (pipeStage_Concurrent0 >= 2) {
	    /* Delay: '<S3>/TmpDelayBufferAtDraw Markers1Inport1' */
	    memcpy(&ex_staple_counting_B.TmpDelayBufferAtDrawMarkers1I_i[0],
	           &ex_staple_counting_DW.TmpDelayBufferAtDrawMarkers1I_i[0], 202176U *
	           sizeof(real32_T));
	
	    /* Delay: '<S3>/TmpDelayBufferAtDraw Markers1Inport2' */
	    line_idx_1 = (int32_T)ex_staple_counting_DW.CircBufIdx * 100;
	    memcpy(&ex_staple_counting_B.TmpDelayBufferAtDrawMarkers1Inp[0],
	           &ex_staple_counting_DW.TmpDelayBufferAtDrawMarkers1Inp[line_idx_1],
	           100U * sizeof(real_T));
...
        }
void ex_staple_counting_Concurrent0(void)
	{
...
	
	#pragma omp parallel num_threads(3)
	
	  {
	#pragma omp sections
	
	    {
	
	#pragma omp section
	
	      {
	        ex_staple_counting_ThreadFcn0();
	      }
	
	#pragma omp section
	
	      {
	        ex_staple_counting_ThreadFcn1();
	      }
	
	#pragma omp section
	
	      {
	        ex_staple_counting_ThreadFcn2();
	      }
	    }
	  }

Смотрите также

Похожие темы