Чтобы повысить эффективность выполнения, генератор кода может изменить порядок выполнения блока. В диалоговом окне Configuration Parameters, когда вы устанавливаете Оптимизировать параметр Порядка Блока на Improved Execution Speed
, генератор кода может изменить порядок блочной операции реализовать эту оптимизацию:
Устраните копии данных для блоков, которые выполняют оперативные операции (то есть, используйте ту же переменную ввода и вывода), и содержите код алгоритма с ненужными копиями данных.
Объедините больше циклов for
путем выполнения блоков вместе, которые имеют тот же размер.
Снова используйте ту же переменную для входа, выведите, и состояние блока Unit Delay путем выполнения блока Unit Delay перед восходящими блоками.
Эта оптимизация улучшает скорость выполнения и сохраняет потребление ROM и RAM.
Откройте модель matlab:rtwdemo_optimizeblockorder. Эта модель содержит три подсистемы для демонстрации, как переупорядочение блочных операций повышает эффективность выполнения.
for
LoopFusionScheduling
подсистемы показывает, как генератор кода переупорядочивает блочные операции так, чтобы блоки, которые имеют тот же выходной размер, выполнились вместе. Это переупорядочение включает сплав цикла for
. Установите порядок блока Optimize в параметре сгенерированного кода к Off
.
Во временной папке вашей системы создайте папку для сборки и инспекционного процесса и создайте модель.
### Starting build procedure for model: rtwdemo_optimizeblockorder ### Successful completion of build procedure for model: rtwdemo_optimizeblockorder
Просмотрите сгенерированный код без оптимизации. Код для подсистемы 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
для двух комбинаций блоков Усиления и Смещения и блоков продукта.
Сгенерируйте код с оптимизацией. Установите порядок блока Optimize в параметре сгенерированного кода к Improved Execution Speed
и создайте модель.
### Starting build procedure for model: rtwdemo_optimizeblockorder ### Successful completion of build procedure for model: rtwdemo_optimizeblockorder
Просмотрите сгенерированный код с оптимизацией.
/* 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] = rty_Out4[3 * i + i_0] + rtu_In4[tmp_0] * rtu_In3[i_0]; /* Product: '<S2>/Product' incorporates: * Product: '<S2>/Product1' */ tmp_0++; rty_Out2[tmp] += rtu_In2[tmp_0] * rtu_In1[i_0 + 3]; /* Product: '<S2>/Product1' */ rty_Out4[tmp] += rtu_In4[tmp_0] * 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; } }
В оптимизированном коде блоки с тем же выходным размером выполняются вместе. Два набора блоков Усиления и Смещения имеют выходной размер размерности 6
, таким образом, они выполняются вместе. Блоки продукта имеют выходной размер размерности 9
, таким образом, они выполняются вместе. Сплав циклов for
позволяет генератору кода установить значение выражения 3 * i + i_0
, равный временной переменной tmp_0
. Эта оптимизация также повышает эффективность выполнения.
Подсистема, которую показывает RegionScheduling
, как генератор кода переупорядочивает блочные операции, чтобы включить буферное повторное использование для входа, выведи, и состояние блоков Единичной задержки. Когда вычисление является частью отдельных областей, которые соединяются только через блоки Задержки, генератор кода может изменить порядок выполнения блока так, чтобы нисходящие области выполнились перед восходящими областями. Этот порядок выполнения включает максимальное повторное использование состояний блока Задержки и переменных ввода и вывода. Установите порядок блока Optimize в параметре сгенерированного кода к Off
и создайте модель.
### Starting build procedure for model: rtwdemo_optimizeblockorder ### Successful completion of build procedure for model: rtwdemo_optimizeblockorder
Просмотрите сгенерированный код без оптимизации. Код для подсистемы 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) { int32_T i; real_T rtb_Sum; 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 model: rtwdemo_optimizeblockorder ### Successful completion of build procedure for model: rtwdemo_optimizeblockorder
Просмотрите сгенерированный код с оптимизацией.
/* 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
подсистемы показывает, как генератор кода переупорядочивает блочные операции, чтобы устранить копии данных для блоков, которые выполняют оперативные операции. В диалоговом окне Configuration Parameters, установленном порядок блока Optimize в параметре сгенерированного кода к Off
и, создают модель.
### Starting build procedure for model: rtwdemo_optimizeblockorder ### Successful completion of build procedure for model: rtwdemo_optimizeblockorder
Просмотрите сгенерированный код без оптимизации. Код для подсистемы InplaceScheduling
:
/* Output and update for atomic system: '<Root>/InplaceScheduling' */ static void InplaceScheduling(void) { int32_T idx1; int32_T idx2; real_T acc; int32_T k; real_T rtb_Max[6]; 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' */ if (2.0 > rtDWork.UnitDelay_DSTATE[idx1]) { rtb_Max[idx1] = 2.0; } else { rtb_Max[idx1] = rtDWork.UnitDelay_DSTATE[idx1]; } /* 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' * UnitDelay: '<S1>/Unit Delay' */ if (rtU.In9[k] > 0.0) { rtDWork.UnitDelay_DSTATE[k] = 0.0; } else { rtDWork.UnitDelay_DSTATE[k] = rtb_Max[k]; } /* End of Switch: '<S1>/Switch' */ } /* End of S-Function (sdsp2norm2): '<S1>/Normalization' */ }
С порядком выполнения по умолчанию блок Max выполняется перед блоком продукта. Чтобы содержать блок Sum вывод, сгенерированный код содержит две переменные, UnitDelay_DSTATE
и rtb_Max
.
Сгенерируйте код с оптимизацией. Установите порядок блока Optimize в параметре сгенерированного кода к Improved Execution Speed
и создайте модель.
### Starting build procedure for model: rtwdemo_optimizeblockorder ### Successful completion of build procedure for model: rtwdemo_optimizeblockorder
Просмотрите сгенерированный код с оптимизацией.
/* Output and update for atomic system: '<Root>/InplaceScheduling' */ static void InplaceScheduling(void) { real_T rtb_Max[6]; int32_T idx2; real_T acc; int32_T k; int32_T i; for (i = 0; i < 6; i++) { /* Sum: '<S1>/Sum2x3' incorporates: * Inport: '<Root>/In7' * UnitDelay: '<S1>/Unit Delay' */ acc = rtU.In7[i] + rtDWork.UnitDelay_DSTATE[i]; /* Outport: '<Root>/Out6' incorporates: * Bias: '<S1>/Bias' * Inport: '<Root>/In8' * Product: '<S1>/Product' */ rtY.Out6[i] = (rtU.In8 + 1.0) * acc; /* MinMax: '<S1>/Max' */ if (2.0 > acc) { acc = 2.0; } /* End of MinMax: '<S1>/Max' */ /* Switch: '<S1>/Switch' incorporates: * Inport: '<Root>/In9' * UnitDelay: '<S1>/Unit Delay' */ if (rtU.In9[i] > 0.0) { rtDWork.UnitDelay_DSTATE[i] = 0.0; } else { rtDWork.UnitDelay_DSTATE[i] = acc; } /* End of Switch: '<S1>/Switch' */ /* Sum: '<S1>/Sum2x3' */ rtb_Max[i] = acc; } /* S-Function (sdsp2norm2): '<S1>/Normalization' incorporates: * Outport: '<Root>/Out7' */ i = 0; idx2 = 0; acc = 0.0; for (k = 0; k < 6; k++) { acc += rtb_Max[i] * rtb_Max[i]; i++; } acc = 1.0 / (sqrt(acc) + 1.0E-10); for (k = 0; k < 6; k++) { rtY.Out7[idx2] = rtb_Max[idx2] * acc; idx2++; } /* End of S-Function (sdsp2norm2): '<S1>/Normalization' */ }
Оптимизированный код не содержит переменную rtb_Max
или копию данных. Сгенерированный код содержит одну переменную, UnitDelay_DSTATE
, для содержания блока Sum вывод. Блок продукта читает из UnitDelay_DSTATE
и чтений блока Max от и пишет в UnitDelay_DSTATE
.
Чтобы реализовать буферное повторное использование, генератор кода не нарушает заданные пользователями приоритеты блока.
Оптимизируйте порядок блочной операции в сгенерированном коде