Как предотвратить векторную оптимизацию работы этой функции с помощью компилятора arm-none-eabi-gcc?
Мой код
Я работаю с простым кодом, который использует эту функцию в академическом проекте:
void calculateDistanceMatrix(const float data[M][N],
float distance[M][N]) {
float sum = 0.0;
for(int i = 0; i < M; i++) {
for(int j = i+1; j < M; j++) {
for(int k = 0; k < N; w++) {
sum += (data[i][k] - data[j][k]) *
(data[i][k] - data[j][k]);
}
distance[i][j] = sum;
distance[j][i] = sum;
distance[i][i] = 0.0;
sum = 0.0;
}
}
}
Моя целевая архитектура
Мой код должен выполнять не более чем эту простую матричную операцию над "данными" и заполнять матрицу "расстояний" результатами. Однако в моем академическом проекте меня интересует, как компилятор оптимизирует эти векторные операции для архитектуры ARM, с которой я работаю. Командная строка для компиляции содержит следующее:
arm-none-eabi-gcc <flags> <my_sources> -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard <more_flags>
Моя программа предназначена для запуска на встроенном устройстве Xilinx Zynq-7000, архитектура которого включает оптимизированный набор NEON для векторных операций (описан в этой хорошей презентации)
Моя проблема
Я должен отслеживать производительность выполнения векторных операций в функции "CalculateDatMatrix" с оптимизацией компилятора и без него. Я заметил, что вывод сборки включает в себя общие инструкции NEON и VFP для векторной загрузки и операций хранения (подробно описано в справочнике по ассемблеру ARM для версии 5.0):
ecf37a01 vldmia r3!, {s15}
ecf26a01 vldmia r2!, {s13}
e1530000 cmp r3, r0
ee777ae6 vsub.f32 s15, s15, s13
ee077aa7 vmla.f32 s14, s15, s15
1afffff9 bne 68 <calculateDistanceMatrix+0x48>
eca17a01 vstmia r1!, {s14}
Я не смог найти способ скомпилировать этот код так, чтобы эти оптимизированные инструкции не использовались.
Знаете ли вы какую-либо конфигурацию компиляции или хитрость кода, которая могла бы избежать этих инструкций? Ценю любую помощь по этому вопросу.
2 ответа
Я вернулся к этой проблеме и обнаружил, что моя среда была настроена на сборку в режиме отладки, поэтому никакой оптимизации не было.
Фактически оптимизированный код использует инструкции VLDM и VSTM. Они не генерируются, однако, когда я добавляю прагму
#pragma GCC optimize ("O0")
в моем исходном файле.
Приведенные вами инструкции не являются векторными операциями:vsub.f32 s15, s13, s15
Это простое 32-битное вычитание с плавающей точкой. Вы можете сказать, используя 32-битную форму S-регистра и .f32
суффикс в инструкции