Быстро 4x4 умножение матриц в C

YouTube обеспечивает ActionScript API.

Используя это, Вы могли загрузить видео в Flash с помощью их API и затем иметь приложение Flash, создают аннотации на слой выше видео.

Или, альтернативно, если Вы хотите избегать создания чего-то в Flash, с помощью API JavaScript YouTube, Вы могли бы привлечь ОТДЕЛЕНИЯ HTML по плееру YouTube на Вашей веб-странице. Просто помните при встраивании плеера для имения WMODE="transparent" в списке параметрических усилителей.

Настолько использующий пример с YouTube:

  

И затем необходимо быть в состоянии нарисовать аннотации по фильму YouTube с помощью CSS/DHTML.

16
задан Nils Pipenbrinck 4 November 2009 в 14:53
поделиться

5 ответов

No, the Strassen or Coppersmith-Winograd algorithm wouldn't make much difference here. They start to pay off for larger matrices only.

If your matrix-multiplication is really a bottleneck you could rewrite the algorithm using NEON SIMD instructions. That would only help for ARMv7 as ARMv6 does not has this extension though.

I'd expect a factor 3 speedup over the compiled C-code for your case.

EDIT: You can find a nice implementation in ARM-NEON here: http://code.google.com/p/math-neon/

For your C-code there are two things you could do to speed up the code:

  1. Don't inline the function. Your matrix multiplication generates quite a bit of code as it's unrolled, and the ARM only has a very tiny instruction cache. Excessive inlining can make your code slower because the CPU will be busy loading code into the cache instead of executing it.

  2. Use the restrict keyword to tell the compiler that the source- and destination pointers don't overlap in memory. Currently the compiler is forced to reload every source value from memory whenever a result is written because it has to assume that source and destination may overlap or even point to the same memory.

36
ответ дан 30 November 2019 в 15:16
поделиться

Просто придирки. Интересно, почему люди до сих пор добровольно запутывают свой код? C уже трудно читать, добавлять к нему не нужно.

static inline void Matrix4x4MultiplyBy4x4 (float src1[4][4], float src2[4][4], float dest[4][4])
{
dest[0][0] = src1[0][0] * src2[0][0] + src1[0][1] * src2[1][0] + src1[0][2] * src2[2][0] + src1[0][3] * src2[3][0]; 
dest[0][1] = src1[0][0] * src2[0][1] + src1[0][1] * src2[1][1] + src1[0][2] * src2[2][1] + src1[0][3] * src2[3][1]; 
dest[0][2] = src1[0][0] * src2[0][2] + src1[0][1] * src2[1][2] + src1[0][2] * src2[2][2] + src1[0][3] * src2[3][2]; 
dest[0][3] = src1[0][0] * src2[0][3] + src1[0][1] * src2[1][3] + src1[0][2] * src2[2][3] + src1[0][3] * src2[3][3]; 
dest[1][0] = src1[1][0] * src2[0][0] + src1[1][1] * src2[1][0] + src1[1][2] * src2[2][0] + src1[1][3] * src2[3][0]; 
dest[1][1] = src1[1][0] * src2[0][1] + src1[1][1] * src2[1][1] + src1[1][2] * src2[2][1] + src1[1][3] * src2[3][1]; 
dest[1][2] = src1[1][0] * src2[0][2] + src1[1][1] * src2[1][2] + src1[1][2] * src2[2][2] + src1[1][3] * src2[3][2]; 
dest[1][3] = src1[1][0] * src2[0][3] + src1[1][1] * src2[1][3] + src1[1][2] * src2[2][3] + src1[1][3] * src2[3][3]; 
dest[2][0] = src1[2][0] * src2[0][0] + src1[2][1] * src2[1][0] + src1[2][2] * src2[2][0] + src1[2][3] * src2[3][0]; 
dest[2][1] = src1[2][0] * src2[0][1] + src1[2][1] * src2[1][1] + src1[2][2] * src2[2][1] + src1[2][3] * src2[3][1]; 
dest[2][2] = src1[2][0] * src2[0][2] + src1[2][1] * src2[1][2] + src1[2][2] * src2[2][2] + src1[2][3] * src2[3][2]; 
dest[2][3] = src1[2][0] * src2[0][3] + src1[2][1] * src2[1][3] + src1[2][2] * src2[2][3] + src1[2][3] * src2[3][3]; 
dest[3][0] = src1[3][0] * src2[0][0] + src1[3][1] * src2[1][0] + src1[3][2] * src2[2][0] + src1[3][3] * src2[3][0]; 
dest[3][1] = src1[3][0] * src2[0][1] + src1[3][1] * src2[1][1] + src1[3][2] * src2[2][1] + src1[3][3] * src2[3][1]; 
dest[3][2] = src1[3][0] * src2[0][2] + src1[3][1] * src2[1][2] + src1[3][2] * src2[2][2] + src1[3][3] * src2[3][2]; 
dest[3][3] = src1[3][0] * src2[0][3] + src1[3][1] * src2[1][3] + src1[3][2] * src2[2][3] + src1[3][3] * src2[3][3]; 
};
20
ответ дан 30 November 2019 в 15:16
поделиться

Are you sure that your unrolled code is faster than the explicit loop based approach? Mind that the compilers are usually better than humans performing optimizations!

In fact, I'd bet there are more chances for a compiler to emit automatically SIMD instructions from a well written loop than from a series of "unrelated" statements...

You could also specify the matrices sizes in the argument declaration. Then you could use the normal bracket syntax to access the elements, and it could also be a good hint for the compiler to make its optimisations too.

3
ответ дан 30 November 2019 в 15:16
поделиться

Ваш полностью развернутый традиционный продукт, скорее всего, будет довольно быстрым.

Ваша матрица слишком мала, чтобы преодолеть подслушанное управление умножением Штрассена в его традиционной форме с явными индексами и кодом разделения; вы, вероятно, потеряете какое-либо влияние на оптимизацию из-за этих накладных расходов.

Но если вы хотите побыстрее, я бы использовал инструкции SIMD, если они доступны. Я был бы удивлен, если в наши дни чипы ARM не имеют их. Если они это сделают, вы можете управлять всеми продуктами в строке / столбце в одной инструкции; если SIMD имеет ширину 8, вы можете управлять умножениями на 2 строк / столбцов в одной инструкции. Настройка операндов для выполнения этой инструкции может потребовать некоторого танца; Инструкции SIMD легко подберут ваши строки (соседние значения), но не подберут столбцы (несмежные).

2
ответ дан 30 November 2019 в 15:16
поделиться

Это произвольные матрицы или у них есть какие-то симметрии? Если это так, эти симметрии часто можно использовать для повышения производительности (например, в матрицах вращения).

Кроме того, я согласен с вышеупомянутым fortran и буду запускать некоторые временные тесты, чтобы убедиться, что ваш развернутый вручную код работает быстрее, чем оптимизирующий компилятор может создать. По крайней мере, вы сможете упростить свой код.

Пол

2
ответ дан 30 November 2019 в 15:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: