Чтобы улучшить эффективность выполнения, генератор кода может изменить порядок выполнения блока. В диалоговом окне Параметров конфигурации, когда вы устанавливаете параметр Optimize Блока Порядка равным Improved Execution Speed
генератор кода может изменить порядок операции блока, чтобы реализовать эти оптимизации:
Исключить копии данных для блоков, которые выполняют операции inplace (то есть используют ту же входную и выходную переменную) и содержат код алгоритма с ненужными копиями данных.
Объедините больше for
циклы путем выполнения блоков вместе с одинаковым размером.
Повторно используйте ту же переменную для входа, вывода и состояния блока Unit Delay путем выполнения блока Unit Delay перед вышестоящими блоками.
Эти оптимизации улучшают скорость выполнения и сохраняют потребление ОЗУ и ПЗУ.
Откройте matlab:rtwdemo_optimizeblockorder модели. Эта модель содержит три подсистемы для демонстрации того, как операции переупорядочивания блоков улучшают эффективность выполнения.
for
Циклическое слияниеПодсистема LoopFusionScheduling
показывает, как генератор кода переупорядочивает операции блока так, чтобы блоки с одинаковым размером выхода выполнялись вместе. Это переупорядочивание позволяет for
цикл. Установите порядок блоков Optimize в сгенерированном параметре сгенерированного кода равным Off
.
Во временной папке вашей системы создайте папку для процесса сборки и проверки и создайте модель.
### Starting build procedure for: rtwdemo_optimizeblockorder ### Successful completion of build procedure for: rtwdemo_optimizeblockorder Build Summary Top model targets built: Model Action Rebuild Reason =========================================================================================================== rtwdemo_optimizeblockorder Code generated and compiled Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 12.873s
Просмотрите сгенерированный код без оптимизации. Код для LoopFusionScheduling
подсистема:
/* Output and update for atomic system: '<Root>/LoopFusionScheduling' */ static void LoopFusionScheduling(const real_T rtu_In1[6], const real_T rtu_In2[6], const real_T rtu_In3[6], const real_T rtu_In4[6], real_T rty_Out1[6], real_T rty_Out2[9], real_T rty_Out3[6], real_T rty_Out4[9]) { int32_T i; int32_T i_0; int32_T tmp; int32_T tmp_0; /* Bias: '<S2>/Bias' incorporates: * Gain: '<S2>/Gain' */ for (i = 0; i < 6; i++) { rty_Out1[i] = -0.3 * rtu_In1[i] + 0.5; } /* End of Bias: '<S2>/Bias' */ /* Product: '<S2>/Product' */ for (i = 0; i < 3; i++) { for (i_0 = 0; i_0 < 3; i_0++) { tmp = i_0 + 3 * i; rty_Out2[tmp] = 0.0; tmp_0 = i << 1; rty_Out2[tmp] += rtu_In2[tmp_0] * rtu_In1[i_0]; rty_Out2[tmp] += rtu_In2[tmp_0 + 1] * rtu_In1[i_0 + 3]; } } /* End of Product: '<S2>/Product' */ /* Bias: '<S2>/Bias1' incorporates: * Gain: '<S2>/Gain1' */ for (i = 0; i < 6; i++) { rty_Out3[i] = -0.3 * rtu_In3[i] + 0.5; } /* End of Bias: '<S2>/Bias1' */ /* Product: '<S2>/Product1' */ for (i = 0; i < 3; i++) { for (i_0 = 0; i_0 < 3; i_0++) { tmp = i_0 + 3 * i; rty_Out4[tmp] = 0.0; tmp_0 = i << 1; rty_Out4[tmp] += rtu_In4[tmp_0] * rtu_In3[i_0]; rty_Out4[tmp] += rtu_In4[tmp_0 + 1] * rtu_In3[i_0 + 3]; } } /* End of Product: '<S2>/Product1' */ }
С порядком выполнения по умолчанию блоки выполняются слева направо и сверху вниз. В результате существуют отдельные for
циклы для двух комбинаций блоков Gain и Bias и блоков Product.
Сгенерируйте код с оптимизацией. Установите порядок блоков Optimize в сгенерированном параметре сгенерированного кода равным Improved Execution Speed
и создайте модель.
### Starting build procedure for: rtwdemo_optimizeblockorder ### Successful completion of build procedure for: rtwdemo_optimizeblockorder Build Summary Top model targets built: Model Action Rebuild Reason ========================================================================================== rtwdemo_optimizeblockorder Code generated and compiled Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 9.8141s
Просмотрите сгенерированный код с оптимизацией.
/* Output and update for atomic system: '<Root>/LoopFusionScheduling' */ static void LoopFusionScheduling(const real_T rtu_In1[6], const real_T rtu_In2[6], const real_T rtu_In3[6], const real_T rtu_In4[6], real_T rty_Out1[6], real_T rty_Out2[9], real_T rty_Out3[6], real_T rty_Out4[9]) { int32_T i; int32_T i_0; int32_T tmp; int32_T tmp_0; for (i = 0; i < 3; i++) { for (i_0 = 0; i_0 < 3; i_0++) { /* Product: '<S2>/Product' incorporates: * Product: '<S2>/Product1' */ tmp = i_0 + 3 * i; rty_Out2[tmp] = 0.0; /* Product: '<S2>/Product1' */ rty_Out4[tmp] = 0.0; /* Product: '<S2>/Product' incorporates: * Product: '<S2>/Product1' */ tmp_0 = i << 1; rty_Out2[tmp] += rtu_In2[tmp_0] * rtu_In1[i_0]; /* Product: '<S2>/Product1' */ rty_Out4[tmp] += rtu_In4[tmp_0] * rtu_In3[i_0]; /* Product: '<S2>/Product' */ rty_Out2[tmp] += rtu_In2[tmp_0 + 1] * rtu_In1[i_0 + 3]; /* Product: '<S2>/Product1' incorporates: * Product: '<S2>/Product' */ rty_Out4[tmp] += rtu_In4[tmp_0 + 1] * rtu_In3[i_0 + 3]; } } for (i = 0; i < 6; i++) { /* Bias: '<S2>/Bias' incorporates: * Gain: '<S2>/Gain' */ rty_Out1[i] = -0.3 * rtu_In1[i] + 0.5; /* Bias: '<S2>/Bias1' incorporates: * Gain: '<S2>/Gain1' */ rty_Out3[i] = -0.3 * rtu_In3[i] + 0.5; } }
В оптимизированном коде блоки с таким же размером выхода выполняются вместе. Два набора блоков Gain и Bias имеют выходной размер размерности 6
так они казнят вместе. Блоки Продукта имеют выход размерности размер 9
так они казнят вместе. Слияние for
циклы позволяет генератору кода задать значение выражения 3 * i + i_0
равной временной переменной tmp_0
. Эта оптимизация также повышает эффективность выполнения.
Подсистема RegionScheduling
показывает, как генератор кода переупорядочивает операции блока, чтобы включить повторное использование буфера для входных, выходных и состояний блоков Unit Delay. Когда расчет является частью отдельных областей, которые соединяются только через блоки Delay, генератор кода может изменить порядок выполнения блока, чтобы нисходящие области выполнялись перед областями в восходящем направлении. Этот порядок выполнения позволяет максимально повторно использовать состояния блока Delay и входные и выходные переменные. Установите порядок блоков Optimize в сгенерированном параметре сгенерированного кода равным Off
и создайте модель.
### Starting build procedure for: rtwdemo_optimizeblockorder ### Successful completion of build procedure for: rtwdemo_optimizeblockorder Build Summary Top model targets built: Model Action Rebuild Reason ========================================================================================== rtwdemo_optimizeblockorder Code generated and compiled Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 9.6046s
Просмотрите сгенерированный код без оптимизации. Код для RegionScheduling
подсистема:
/* Output and update for atomic system: '<Root>/RegionScheduling' */ static void RegionScheduling(const real_T rtu_In1[6], const real_T rtu_In2[6], real_T rty_Out1[6], rtDW_RegionScheduling *localDW) { real_T rtb_Sum; int32_T i; for (i = 0; i < 6; i++) { /* Sum: '<S3>/Sum' incorporates: * UnitDelay: '<S3>/Delay' * UnitDelay: '<S3>/UnitDelay' */ rtb_Sum = localDW->Delay_DSTATE[i] + localDW->UnitDelay_DSTATE[i]; /* UnitDelay: '<S3>/UnitDelay2' */ rty_Out1[i] = localDW->UnitDelay2_DSTATE[i]; /* Update for UnitDelay: '<S3>/Delay' incorporates: * Bias: '<S3>/Bias' */ localDW->Delay_DSTATE[i] = rtu_In1[i] + 3.0; /* Update for UnitDelay: '<S3>/UnitDelay' incorporates: * Gain: '<S3>/Gain' */ localDW->UnitDelay_DSTATE[i] = 2.0 * rtu_In2[i]; /* Update for UnitDelay: '<S3>/UnitDelay2' */ localDW->UnitDelay2_DSTATE[i] = rtb_Sum; } }
С порядком выполнения по умолчанию сгенерированный код содержит дополнительную временную переменную rtb_Sum
и копию данных.
Сгенерируйте код с оптимизацией. Установите порядок блоков Optimize в сгенерированном параметре сгенерированного кода равным Improved Execution Speed
и создайте модель.
### Starting build procedure for: rtwdemo_optimizeblockorder ### Successful completion of build procedure for: rtwdemo_optimizeblockorder Build Summary Top model targets built: Model Action Rebuild Reason ========================================================================================== rtwdemo_optimizeblockorder Code generated and compiled Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 9.8528s
Просмотрите сгенерированный код с оптимизацией.
/* Output and update for atomic system: '<Root>/RegionScheduling' */ static void RegionScheduling(const real_T rtu_In1[6], const real_T rtu_In2[6], real_T rty_Out1[6], rtDW_RegionScheduling *localDW) { int32_T i; for (i = 0; i < 6; i++) { /* UnitDelay: '<S3>/UnitDelay2' */ rty_Out1[i] = localDW->UnitDelay2_DSTATE[i]; /* Sum: '<S3>/Sum' incorporates: * UnitDelay: '<S3>/Delay' * UnitDelay: '<S3>/UnitDelay' * UnitDelay: '<S3>/UnitDelay2' */ localDW->UnitDelay2_DSTATE[i] = localDW->Delay_DSTATE[i] + localDW->UnitDelay_DSTATE[i]; /* Bias: '<S3>/Bias' incorporates: * UnitDelay: '<S3>/Delay' */ localDW->Delay_DSTATE[i] = rtu_In1[i] + 3.0; /* Gain: '<S3>/Gain' incorporates: * UnitDelay: '<S3>/UnitDelay' */ localDW->UnitDelay_DSTATE[i] = 2.0 * rtu_In2[i]; } }
В оптимизированном коде блоки в областях 3, 2 и 1 выполняются в этом порядке. С этим порядком выполнения сгенерированный код не содержит временную переменную rtb_Sum
и соответствующую копию данных.
Подсистема InplaceScheduling
показывает, как генератор кода переупорядочивает операции блока, чтобы исключить копии данных для блоков, которые выполняют операции inplace. В Параметры конфигурации окне установите Порядок блока Оптимизации в параметре сгенерированного кода равным Off
и создайте модель.
### Starting build procedure for: rtwdemo_optimizeblockorder ### Successful completion of build procedure for: rtwdemo_optimizeblockorder Build Summary Top model targets built: Model Action Rebuild Reason ========================================================================================== rtwdemo_optimizeblockorder Code generated and compiled Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 9.2423s
Просмотрите сгенерированный код без оптимизации. Код для InplaceScheduling
подсистема:
/* Output and update for atomic system: '<Root>/InplaceScheduling' */ static void InplaceScheduling(void) { real_T rtb_Max[6]; real_T acc; int32_T idx1; int32_T idx2; int32_T k; for (idx1 = 0; idx1 < 6; idx1++) { /* Sum: '<S1>/Sum2x3' incorporates: * Inport: '<Root>/In7' * UnitDelay: '<S1>/Unit Delay' */ rtDWork.UnitDelay_DSTATE[idx1] += rtU.In7[idx1]; /* MinMax: '<S1>/Max' */ acc = rtDWork.UnitDelay_DSTATE[idx1]; if (2.0 > acc) { rtb_Max[idx1] = 2.0; } else { rtb_Max[idx1] = acc; } /* End of MinMax: '<S1>/Max' */ } /* S-Function (sdsp2norm2): '<S1>/Normalization' incorporates: * Outport: '<Root>/Out7' */ idx1 = 0; idx2 = 0; acc = 0.0; for (k = 0; k < 6; k++) { acc += rtb_Max[idx1] * rtb_Max[idx1]; idx1++; } acc = 1.0 / (sqrt(acc) + 1.0E-10); for (k = 0; k < 6; k++) { rtY.Out7[idx2] = rtb_Max[idx2] * acc; idx2++; /* Outport: '<Root>/Out6' incorporates: * Bias: '<S1>/Bias' * Inport: '<Root>/In8' * Outport: '<Root>/Out7' * Product: '<S1>/Product' */ rtY.Out6[k] = (rtU.In8 + 1.0) * rtDWork.UnitDelay_DSTATE[k]; /* Switch: '<S1>/Switch' incorporates: * Inport: '<Root>/In9' */ if (rtU.In9[k] > 0.0) { /* Update for UnitDelay: '<S1>/Unit Delay' */ rtDWork.UnitDelay_DSTATE[k] = 0.0; } else { /* Update for UnitDelay: '<S1>/Unit Delay' */ rtDWork.UnitDelay_DSTATE[k] = rtb_Max[k]; } /* End of Switch: '<S1>/Switch' */ } /* End of S-Function (sdsp2norm2): '<S1>/Normalization' */ }
С порядком выполнения по умолчанию блок Max выполняется перед блоком Product. Чтобы сохранить выход блока Sum, сгенерированный код содержит две переменные, UnitDelay_DSTATE
и rtb_Max
.
Сгенерируйте код с оптимизацией. Установите порядок блоков Optimize в сгенерированном параметре сгенерированного кода равным Improved Execution Speed
и создайте модель.
### Starting build procedure for: rtwdemo_optimizeblockorder ### Successful completion of build procedure for: rtwdemo_optimizeblockorder Build Summary Top model targets built: Model Action Rebuild Reason ========================================================================================== rtwdemo_optimizeblockorder Code generated and compiled Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 9.9044s
Просмотрите сгенерированный код с оптимизацией.
/* Output and update for atomic system: '<Root>/InplaceScheduling' */ static void InplaceScheduling(void) { real_T acc; int32_T idx1; int32_T idx2; int32_T k; for (idx1 = 0; idx1 < 6; idx1++) { /* Sum: '<S1>/Sum2x3' incorporates: * Inport: '<Root>/In7' * UnitDelay: '<S1>/Unit Delay' */ rtDWork.UnitDelay_DSTATE[idx1] += rtU.In7[idx1]; /* Outport: '<Root>/Out6' incorporates: * Bias: '<S1>/Bias' * Inport: '<Root>/In8' * Product: '<S1>/Product' */ rtY.Out6[idx1] = (rtU.In8 + 1.0) * rtDWork.UnitDelay_DSTATE[idx1]; /* MinMax: '<S1>/Max' */ acc = rtDWork.UnitDelay_DSTATE[idx1]; if (2.0 > acc) { rtDWork.UnitDelay_DSTATE[idx1] = 2.0; } else { rtDWork.UnitDelay_DSTATE[idx1] = acc; } /* End of MinMax: '<S1>/Max' */ } /* S-Function (sdsp2norm2): '<S1>/Normalization' incorporates: * Outport: '<Root>/Out7' */ idx1 = 0; idx2 = 0; acc = 0.0; for (k = 0; k < 6; k++) { acc += rtDWork.UnitDelay_DSTATE[idx1] * rtDWork.UnitDelay_DSTATE[idx1]; idx1++; } acc = 1.0 / (sqrt(acc) + 1.0E-10); for (k = 0; k < 6; k++) { rtY.Out7[idx2] = rtDWork.UnitDelay_DSTATE[idx2] * acc; idx2++; } /* End of S-Function (sdsp2norm2): '<S1>/Normalization' */ /* Update for UnitDelay: '<S1>/Unit Delay' */ for (idx1 = 0; idx1 < 6; idx1++) { /* Switch: '<S1>/Switch' incorporates: * Inport: '<Root>/In9' */ if (rtU.In9[idx1] > 0.0) { rtDWork.UnitDelay_DSTATE[idx1] = 0.0; } /* End of Switch: '<S1>/Switch' */ } /* End of Update for UnitDelay: '<S1>/Unit Delay' */ }
Оптимизированный код не содержит переменную rtb_Max
или копий. Данные содержат одну переменную, UnitDelay_DSTATE
, для удержания вывода блока Sum. Блок Product читается с UnitDelay_DSTATE
и блок Max читает и записывает в UnitDelay_DSTATE
.
Чтобы реализовать повторное использование буфера, генератор кода не нарушает заданные пользователем приоритеты блоков.
Оптимизируйте порядок операции блока в сгенерированном коде