День добрый.
Бьюсь с перемножением матриц, но стандартный метод D3DXMatrixMultiply все-равно оказывается быстрее( в коем-то веке )!
Мои реализации перемножения:
#1
_11 = (_11*_mat._11) + (_12*_mat._21) + (_13*_mat._31)+ (_14*_mat._31); _12 = (_11*_mat._12) + (_12*_mat._22) + (_13*_mat._32)+ (_14*_mat._32); _13 = (_11*_mat._13) + (_12*_mat._23) + (_13*_mat._33)+ (_14*_mat._33); _14 = (_11*_mat._14) + (_12*_mat._24) + (_13*_mat._34)+ (_14*_mat._34); _21 = (_21*_mat._11) + (_22*_mat._21) + (_23*_mat._31)+ (_24*_mat._31); _22 = (_21*_mat._12) + (_22*_mat._22) + (_23*_mat._32)+ (_24*_mat._32); _23 = (_21*_mat._13) + (_22*_mat._23) + (_23*_mat._33)+ (_24*_mat._33); _24 = (_21*_mat._14) + (_22*_mat._24) + (_23*_mat._34)+ (_24*_mat._34); _31 = (_31*_mat._11) + (_32*_mat._21) + (_33*_mat._31)+ (_34*_mat._31); _32 = (_31*_mat._12) + (_32*_mat._22) + (_33*_mat._32)+ (_34*_mat._32); _33 = (_31*_mat._13) + (_32*_mat._23) + (_33*_mat._33)+ (_34*_mat._33); _34 = (_31*_mat._14) + (_32*_mat._24) + (_33*_mat._34)+ (_34*_mat._34); _41 = (_41*_mat._11) + (_42*_mat._21) + (_43*_mat._31)+ (_44*_mat._31); _42 = (_41*_mat._12) + (_42*_mat._22) + (_43*_mat._32)+ (_44*_mat._32); _43 = (_41*_mat._13) + (_42*_mat._23) + (_43*_mat._33)+ (_44*_mat._33); _44 = (_41*_mat._14) + (_42*_mat._24) + (_43*_mat._34)+ (_44*_mat._34);
#2
matrix4x4 out; int i,j,k; for (i=0; i<4; i++) { for (j=0; j<4; j++) { out.m[i][j] = m[i][0] * _mat.m[0][j] + m[i][1] * _mat.m[1][j] + m[i][2] * _mat.m[2][j] + m[i][3] * _mat.m[3][j]; } } return out;
Еще куча алгоритмов, в том числе и с использованием SSE, но переплюнуть стандартную DX функцию не удается( да и сделать хотя бы равную производительность тоже)!
Поделитесь своими соображениями по этому поводу, или может быть методами?!)
Исходник от ДХ
D3DX10INLINE D3DXMATRIX D3DXMATRIX::operator + ( CONST D3DXMATRIX& mat ) const { return D3DXMATRIX(_11 + mat._11, _12 + mat._12, _13 + mat._13, _14 + mat._14, _21 + mat._21, _22 + mat._22, _23 + mat._23, _24 + mat._24, _31 + mat._31, _32 + mat._32, _33 + mat._33, _34 + mat._34, _41 + mat._41, _42 + mat._42, _43 + mat._43, _44 + mat._44); }
не оно?
fzr125
Это сложение
Necrys
Монитор севший нифига не видо ((( ща пороюсь
у ДХ вот
D3DX10INLINE D3DXMATRIX D3DXMATRIX::operator * ( CONST D3DXMATRIX& mat ) const { D3DXMATRIX matT; D3DXMatrixMultiply(&matT, this, &mat); return matT; }
Здесь пресловутая D3DXMatrixMultiply остается так и не известной
в wine она описывается как:
+D3DXMATRIX* WINAPI D3DXMatrixMultiply(D3DXMATRIX *pout, CONST D3DXMATRIX *pm1, CONST D3DXMATRIX *pm2) +{ + int i,j; + + for (i=0; i<4; i++) + { + for (j=0; j<4; j++) + { + pout->m[i][j] = pm1->m[i][0] * pm2->m[0][j] + pm1->m[i][1] * pm2->m[1][j] + pm1->m[i][2] * pm2->m[2][j] + pm1->m[i][3] * pm2->m[3][j]; + } + } + return pout; +}
но, опять же, это медленнее чем оригинальная функция
там SSE2 используется, поэтому и быстрее.
SSE не даёт прироста на таких мелочах, даже иногда вредит. Рулед инлайн и кэш-френдли методы, можно эффективно на чистом asm без sse написать и то лучче будет.
Adler
честно говоря - сомневаюсь в этом!
Necrys
да на SSE не особый прирост!
А на счет асемблера, это уже круто! =)
P.s. тут(http://www.gamedev.ru/code/forum/?id=87885) упоминалось, что на форуме кто-то уже делал функцию mul4x4 на SSE с хорошей производительностью, но вот видимо пост уже стерли( ибо не могу найти саму реализацию функции ) =\
FearOfTheDark
> #1
по моему тут не правильная формула... результат затирает одну из исходных матриц...
http://www.gamedev.ru/code/articles/?id=4238 - тут вроде бы на SSE оптимизировано делали.
Pushkoff
затирает, но не в этом суть. методов уже куча опробована,в се уступают ДХ
сейчас попробовал еще как у Alex-y
r1 = _mm_mul_ps(_mm_shuffle_ps( A._L1, A._L1, 0x00 ) , B._L1); r2 = _mm_mul_ps(_mm_shuffle_ps( A._L2, A._L2, 0x00 ) , B._L1); r1 =_mm_add_ps(r1, _mm_mul_ps(_mm_shuffle_ps( A._L1, A._L1, 0x55 ) , B._L2)); r2 =_mm_add_ps(r2, _mm_mul_ps(_mm_shuffle_ps( A._L2, A._L2, 0x55 ) , B._L2)); r1 =_mm_add_ps(r1, _mm_mul_ps(_mm_shuffle_ps( A._L1, A._L1, 0xAA ) , B._L3)); r2 =_mm_add_ps(r2, _mm_mul_ps(_mm_shuffle_ps( A._L2, A._L2, 0xAA ) , B._L3)); r1 =_mm_add_ps(r1, _mm_mul_ps(_mm_shuffle_ps( A._L1, A._L1, 0xFF ) , B._L4)); r2 =_mm_add_ps(r1, _mm_mul_ps(_mm_shuffle_ps( A._L2, A._L2, 0xFF ) , B._L4)); res._L1 = r1; res._L2 = r2; r1 = _mm_mul_ps(_mm_shuffle_ps( A._L3, A._L3, 0x00 ) , B._L1); r2 = _mm_mul_ps(_mm_shuffle_ps( A._L4, A._L4, 0x00 ) , B._L1); r1 =_mm_add_ps(r1, _mm_mul_ps(_mm_shuffle_ps( A._L3, A._L3, 0x55 ) , B._L2)); r2 =_mm_add_ps(r2, _mm_mul_ps(_mm_shuffle_ps( A._L4, A._L4, 0x55 ) , B._L2)); r1 =_mm_add_ps(r1, _mm_mul_ps(_mm_shuffle_ps( A._L3, A._L3, 0xAA ) , B._L3)); r2 =_mm_add_ps(r2, _mm_mul_ps(_mm_shuffle_ps( A._L4, A._L4, 0xAA ) , B._L3)); r1 =_mm_add_ps(r1, _mm_mul_ps(_mm_shuffle_ps( A._L3, A._L3, 0xFF ) , B._L4)); r2 =_mm_add_ps(r2, _mm_mul_ps(_mm_shuffle_ps( A._L4, A._L4, 0xFF ) , B._L4)); res._L3 = r1; res._L4 = r2;
и опять, DX, на 30% быстрее!
Самое главное, что в общей массе, ты не выиграешь на этом при написании движка/игры, уже сотни раз тут головы об это били, оптимайзить надо там где тормозит, тут +- ничего не потеряешь, если конечно тысячами скелетку на ЦПУ не считать.
Оптимизировал (не до конца) xna math перемножение матриц, вышло следующее:
Цикл 255 раз
0.000015365 (сек) - d3dx
0.000015924 (сек) - xna (Optimized)
Если ещё посидеть над оптимизацией, спокойно обойти можно д3дх :)
Adler
> там SSE2 используется, поэтому и быстрее.
в зависимости от проца, если есть поддержка 3DNow!!! то используется его инструкции а не SSE.
В майкрософт не дураки сидят. Вчера спрашивал про аналогичное : "Кто-нибудь сделал перемножение М4х4 быстрее , чем D3DX ?" Ответа не последовало. Хотя перемножение матриц - это не узкое место.
Тема в архиве.