Как использовать умножить и накапливать внутренние свойства в ARM Cortex-a8?

как использовать встроенные функции Multiply-Accumulate, предоставляемые GCC?

float32x4_t vmlaq_f32 (float32x4_t , float32x4_t , float32x4_t);

Может кто-нибудь объяснить, какие три параметра я должен передать этой функции. Я имею в виду регистры источника и получателя и что возвращает функция?

Help!!!

Ответ 1

Проще говоря, инструкция vmla делает следующее:

struct 
{
  float val[4];
} float32x4_t


float32x4_t vmla (float32x4_t a, float32x4_t b, float32x4_t c)
{
  float32x4 result;

  for (int i=0; i<4; i++)
  {
    result.val[i] =  b.val[i]*c.val[i]+a.val[i];
  }

  return result;
}

И все это компилируется в одну инструкцию ассемблера: -)

Вы можете использовать этот NEON-ассемблер, в том числе и в типичных матричных умножениях 4x4 для 3D-графики, таких как:

float32x4_t transform (float32x4_t * matrix, float32x4_t vector)
{
  /* in a perfect world this code would compile into just four instructions */
  float32x4_t result;

  result = vml (matrix[0], vector);
  result = vmla (result, matrix[1], vector);
  result = vmla (result, matrix[2], vector);
  result = vmla (result, matrix[3], vector);

  return result;
}

Это экономит пару циклов, потому что вам не нужно добавлять результаты после умножения. Добавление так часто используется, что умножает-накапливает hsa, становясь основным в эти дни (даже x86 добавил их в некоторый набор инструкций SSE).

Также стоит упомянуть: операции умножения с накоплением, такие как очень, распространены в приложениях с линейной алгеброй и DSP (цифровая обработка сигналов). ARM был очень умным и реализовал быстрый путь внутри Cortex-A8 NEON-Core. Этот быстрый путь срабатывает, если первый аргумент (аккумулятор) инструкции VMLA является результатом предыдущей инструкции VML или VMLA. Я мог бы вдаваться в подробности, но в двух словах такая серия инструкций выполняется в четыре раза быстрее, чем серия VML/VADD/VML/VADD.

Взгляните на мое простое умножение матрицы: я сделал именно это. Благодаря этому быстрому пути он будет работать примерно в четыре раза быстрее, чем реализация, написанная с использованием VML и ADD вместо VMLA.

Ответ 2

Google'd для vmlaq_f32, появился ссылка для инструментов компилятора RVCT. Вот что он говорит:

Vector multiply accumulate: vmla -> Vr[i] := Va[i] + Vb[i] * Vc[i]
...
float32x4_t vmlaq_f32 (float32x4_t a, float32x4_t b, float32x4_t c);

и

Для представления векторов определены следующие типы. Типы векторных данных NEON называются в соответствии со следующим шаблоном:  < тип > < размер > x < число дорожек > _t Например, int16x4_t представляет собой вектор, содержащий четыре полосы, каждая из которых содержит подписанное 16-разрядное целое число. В таблице E.1 перечислены типы векторных данных.

IOW, возвращаемое значение из функции будет вектором, содержащим 4 32-битных поплавков, и каждый элемент вектора вычисляется путем умножения соответствующих элементов b и c и добавления содержимого a.

НТН

Ответ 3

result = vml (matrix[0], vector);
result = vmla (result, matrix[1], vector);
result = vmla (result, matrix[2], vector);
result = vmla (result, matrix[3], vector);

Эта последовательность не будет работать. Проблема состоит в том, что x компонент накапливает только x, модулированный строками матрицы, и может быть выражен как:

result.x = vector.x * (matrix[0][0] + matrix[1][0] + matrix[2][0] + matrix[3][0]);

...

Правильная последовательность:

result = vml (matrix[0], vector.xxxx);
result = vmla(result, matrix[1], vector.yyyy);

...

NEON и SSE не имеют встроенного выбора для полей (для каждого вектора требуется 8 бит в кодировании команд). Например, у GLSL/HLSL есть такие возможности, поэтому большинство графических процессоров также имеют.

Альтернативный способ достижения этого:

result.x = dp4(vector, matrix[0]);
result.y = dp4(vector, matrix[1]);

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

Обычно предпочитается последовательность mul, madd, madd, madd, так как она не требует маски записи для целевых регистров регистра.

В противном случае код выглядит хорошо. =)