Их куча, я запутался.
- Что наиболее портабельное? windows/linux/android (gcc/mingw/crystalX-gcc)
- Что наиболее негеморойное?
- Расширения gcc vs специфика отдельных SIMD https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
- Подводные камни, кирпичи и прочее.
- Примеры статьи ссылки для нубов где уделяется время деталям
Вот такое хочется ускорить
mat4 mat4_mul_mat4(mat4 m1, mat4 m2) {
mat4 mat;
mat.xx = (m1.xx * m2.xx) + (m1.xy * m2.yx) + (m1.xz * m2.zx) + (m1.xw * m2.wx);
mat.xy = (m1.xx * m2.xy) + (m1.xy * m2.yy) + (m1.xz * m2.zy) + (m1.xw * m2.wy);
mat.xz = (m1.xx * m2.xz) + (m1.xy * m2.yz) + (m1.xz * m2.zz) + (m1.xw * m2.wz);
mat.xw = (m1.xx * m2.xw) + (m1.xy * m2.yw) + (m1.xz * m2.zw) + (m1.xw * m2.ww);
mat.yx = (m1.yx * m2.xx) + (m1.yy * m2.yx) + (m1.yz * m2.zx) + (m1.yw * m2.wx);
mat.yy = (m1.yx * m2.xy) + (m1.yy * m2.yy) + (m1.yz * m2.zy) + (m1.yw * m2.wy);
mat.yz = (m1.yx * m2.xz) + (m1.yy * m2.yz) + (m1.yz * m2.zz) + (m1.yw * m2.wz);
mat.yw = (m1.yx * m2.xw) + (m1.yy * m2.yw) + (m1.yz * m2.zw) + (m1.yw * m2.ww);
mat.zx = (m1.zx * m2.xx) + (m1.zy * m2.yx) + (m1.zz * m2.zx) + (m1.zw * m2.wx);
mat.zy = (m1.zx * m2.xy) + (m1.zy * m2.yy) + (m1.zz * m2.zy) + (m1.zw * m2.wy);
mat.zz = (m1.zx * m2.xz) + (m1.zy * m2.yz) + (m1.zz * m2.zz) + (m1.zw * m2.wz);
mat.zw = (m1.zx * m2.xw) + (m1.zy * m2.yw) + (m1.zz * m2.zw) + (m1.zw * m2.ww);
mat.wx = (m1.wx * m2.xx) + (m1.wy * m2.yx) + (m1.wz * m2.zx) + (m1.ww * m2.wx);
mat.wy = (m1.wx * m2.xy) + (m1.wy * m2.yy) + (m1.wz * m2.zy) + (m1.ww * m2.wy);
mat.wz = (m1.wx * m2.xz) + (m1.wy * m2.yz) + (m1.wz * m2.zz) + (m1.ww * m2.wz);
mat.ww = (m1.wx * m2.xw) + (m1.wy * m2.yw) + (m1.wz * m2.zw) + (m1.ww * m2.ww);
return mat;
}
И такого много. Будут ли профиты ощутимые? Или нужны более весомые задачи,а на этом профиты будет сожраны накладными расходами?
В целом советам,подсказкам и идеям буду благодарен. Ранее не касался расширений никогда. Сейчас читаю всякое но чем дальше тем больше путанницы. Пока что прихожу к выводу что под хотелки подходит SSE2. Но подумал лучше иметь более одного мнения по этому поводу.
UDP:
Короче в треде оказались правы и такие случаи на x86-64 векторизируются сами по себе хорошо. Так как хотелка заключалась в переносимости то нет смысла прибивать гвоздями к возможностям конкретного процессора а достаточно указывать младшую линейку где нужны нужные оптимизации и указывать её в -mtune
и поддерживать соотвецтвенно. Иначе можно получить просто нерабочие исполняемые файлы. На конкретном камне или серверной логике где всё железо известно можно уже извращаться как угодно естественно и выжимать всё что только можно.
Поигрался по разному
dron@gnu:~/555$ gcc-9 -S -m32 -mfpmath=sse -Ofast -funroll-loops mat.c
cc1: warning: SSE instruction set disabled, using 387 arithmetics
dron@gnu:~/555$ gcc-9 -S -m32 -mfpmath=sse -Ofast -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -m64 -mfpmath=sse -Ofast -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -Ofast -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -Ofast -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -O0 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -Ofast -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -O3 -march=native mat.c
dron@gnu:~/555$ gcc -S -mfpmath=sse -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -O3 mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mssse3 -ffast-math -mfpmath=sse mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -mssse3 -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -msse3 -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -ffast-math -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -O3 -march=x86-64 mat.c
dron@gnu:~/555$ gcc-9 -S mat.c
dron@gnu:~/555$ gcc-9 -S -mfpmath=sse -ffast-math -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -march=x86-64 -O3 -march=native mat.c
dron@gnu:~/555$ gcc-9 -S -mtune=k8-sse3 -O3 mat.c
dron@gnu:~/555$ gcc-9 -S -mtune=k8 -O3 mat.c
...
В текущей сборке с просто -O3 у меня оказалось что уже всё векторизированно. (У меня -03 не вызывает проблем )
и следовательно то что я хотел уже есть. Хотя -mtune=k8
делает ещё буст если свести к реальной программе то 34 кадра анимации 1000 объектов подняло до 40 кадров. Это очень не плохо.
Большие же оптимизации в эту сторону равны отсечению целой массы камней что недопустимо для меня (в смысле просто не хоца)
Явную оптимизацию никто не отменяет конечно, но вот прямо сейчас в этом конкретном случае я вижу что лучше писать код который не будет вызывать проблем компилятору для его оптимизации чем оптимизировать самому. Не потому что это плохо, а потом у что частная оптимизация руками сразу подразумевает либо доп зависимости либо привязку к железу. А мне этого не хочется. Ну вот как то так. С другой стороны конечно если взять и решить поддерживать k8
и выше то есть смысл вручную использовать SSE2
к примеру. Но это уже разве что в целях обучения и увидеть разницу между руки vs компилятор. Но чуть в сторону и компилятор всё равно будет на коне ибо просто смена опции на haswell
при нужном камне естественно порвёт всё как тузик грелку.
На сем. Всё. Всем спасибо и добра.