Самый простой способ нормализовать вектор на месте - это что-то вроде
int n = 3;
float v[3] = {1, 2, 3};
cblas_sscal(n, 1.0 / cblas_snrm2(n, v, 1), v, 1);
Вам нужно будет
#include <cblas.h>
или
#include <vblas.h>
(или оба). Обратите внимание, что некоторые функции находятся в разделе «матрица», когда они работают с векторами.
Если вы хотите использовать функции vDSP, см. Раздел Vector-Scalar Division . Вы можете сделать несколько вещей:
vDSP_dotpr()
, sqrt()
и vDSP_vsdiv()
vDSP_dotpr()
, vrsqrte_f32()
и vDSP_vsmul()
(vrsqrte_f32()
является встроенным в NEON GCC, поэтому вам нужно проверить, что вы компилируете для armv7).
vDSP_rmsqv()
, умножить на sqrt(n)
и vDSP_vsdiv()
Причина, по которой нет функции нормализации вектора, заключается в том, что «вектор» в vDSP означает «много вещей одновременно» (примерно до 4096
/ 8192
) и обязательно «вектор» из линейная алгебра. Нормализовать вектор 1024
-элемента довольно бессмысленно, а быстрая функция для нормализации вектора 3
-элемента не сделает ваше приложение значительно быстрее, поэтому его нет.
Предполагаемое использование vDSP больше похоже на нормализацию векторов 1024
2
- или 3
. Я могу найти несколько способов сделать это:
- Используйте
vDSP_vdist()
, чтобы получить вектор длин, а затем vDSP_vdiv()
. Вы должны использовать vDSP_vdist()
несколько раз для векторов длиной больше 2.
- Используйте
vDSP_vsq()
для возведения в квадрат всех входов, vDSP_vadd()
несколько раз, чтобы добавить их все, что эквивалентно vDSP_vsqrt()
или vDSP_vrsqrt()
и vDSP_vmul()
или vDSP_vdiv()
в зависимости от ситуации. Не должно быть слишком сложно написать эквивалент vDSP_vsqrt()
или vDSP_vrsqrt()
.
- Различные способы, которые притворяются, что ваш ввод - сложный вектор. Вряд ли будет быстрее.
Конечно, если у вас нет 1024 векторов для нормализации, не переусердствуйте.
Примечания:
- Я не использую «2-вектор» и «3-вектор», чтобы избежать путаницы с «вектором» из теории относительности.
- Хороший выбор n - это тот, который почти заполняет ваш кэш данных L1. Это не сложно; они были относительно фиксированными на
32K
около десяти лет или более (они могут быть разделены между виртуальными ядрами в многопоточном ЦП, а у некоторых старых / более дешевых процессоров может быть 16 КБ), поэтому самое большее, что вам нужно сделать, это около 8192
для эксплуатации на месте на поплавках. Возможно, вы захотите немного вычесть пространство стека, и если вы делаете несколько последовательных операций, вы, вероятно, захотите сохранить все это в кэше; 1024
или 2048
кажутся довольно разумными и, вероятно, больше будут попадать в убывающую отдачу. Если вам все равно, измерьте производительность ...