는 내가 지금까지 무엇을 가지고 있습니다 정확한 결과를 제공하십시오. 내가 놓친 게 있니? 그리고 dosent 검색은별로 도움이 보인다 - 모든 결과 중 단지 4 × 4 행렬을하고, 매트 VEC 또는 특별한 마법은 매우 이해하기 읽기 쉽고 단단하지 이잖아 ...
업데이트 : Woho! 나는 마침내 그것을 알아 냈다. 내 논리의 오류 (도움 Peter Cordes 덕분에) 이외에도 _mm_mul_epi32() 문제가 있었는데 생각했던 것처럼 작동하지 않았습니다. 대신 _mm_mullo_epi32()를 사용해야했습니다!
이 코드가 가장 효과적이지는 않지만 우선 올바르게 작동하도록 만들어 졌음을 알았습니다. 이제이를 최적화 할 수 있습니다. 업데이트 2
void matmulSSE(int mat1[N][N], int mat2[N][N], int result[N][N]) {
int i, j, k;
__m128i vA, vB, vR, vSum;
for(i = 0; i < N; ++i) {
for(j = 0; j < N; ++j) {
vR = _mm_setzero_si128();
for(k = 0; k < N; k += 4) {
//result[i][j] += mat1[i][k] * mat2[k][j];
vA = _mm_loadu_si128((__m128i*)&mat1[i][k]);
vB = _mm_insert_epi32(vB, mat2[k][j], 0);
vB = _mm_insert_epi32(vB, mat2[k + 1][j], 1);
vB = _mm_insert_epi32(vB, mat2[k + 2][j], 2);
vB = _mm_insert_epi32(vB, mat2[k + 3][j], 3);
vR = _mm_mullo_epi32(vA, vB);
vR = _mm_hadd_epi32(vR, vR);
vR = _mm_hadd_epi32(vR, vR);
result[i][j] += _mm_extract_epi32(vR, 0);
//DEBUG
//printf("vA: %d, %d, %d, %d\n", vA.m128i_i32[0], vA.m128i_i32[1], vA.m128i_i32[2], vA.m128i_i32[3]);
//printf("vB: %d, %d, %d, %d\n", vB.m128i_i32[0], vB.m128i_i32[1], vB.m128i_i32[2], vB.m128i_i32[3]);
//printf("vR: %d, %d, %d, %d\n", vR.m128i_i32[0], vR.m128i_i32[1], vR.m128i_i32[2], vR.m128i_i32[3]);
//printf("\n");
}
}
}
}
:은 I-K-J 루프 순서 버전 피터스 예 변환. vR에 대한 추가로드 및 저장소에서 내부 루프로 이동해야하지만 vA 설정은 루프 위로 이동할 수 있습니다. 빠른 것으로 나타났습니다.
void matmulSSE_2(int mat1[N][N], int mat2[N][N], int result[N][N]) {
int i, j, k;
__m128i vA, vB, vR;
for(i = 0; i < N; ++i) {
for(k = 0; k < N; ++k) {
vA = _mm_set1_epi32(mat1[i][k]);
for(j = 0; j < N; j += 4) {
//result[i][j] += mat1[i][k] * mat2[k][j];
vB = _mm_loadu_si128((__m128i*)&mat2[k][j]);
vR = _mm_loadu_si128((__m128i*)&result[i][j]);
vR = _mm_add_epi32(vR, _mm_mullo_epi32(vA, vB));
_mm_storeu_si128((__m128i*)&result[i][j], vR);
//DEBUG
//printf("vA: %d, %d, %d, %d\n", vA.m128i_i32[0], vA.m128i_i32[1], vA.m128i_i32[2], vA.m128i_i32[3]);
//printf("vB: %d, %d, %d, %d\n", vB.m128i_i32[0], vB.m128i_i32[1], vB.m128i_i32[2], vB.m128i_i32[3]);
//printf("vR: %d, %d, %d, %d\n", vR.m128i_i32[0], vR.m128i_i32[1], vR.m128i_i32[2], vR.m128i_i32[3]);
//printf("\n");
}
}
}
}
발생하는 문제는 무엇입니까? –
@RushyPanchal 올바른 결과를 얻지 못하고 있습니다. 죄송합니다, 내 게시글에 지정해야합니다 ... – Erlisch
발신자가 'result []'을 (를) 제로합니까? 그렇지 않다면 먼저 그렇게해야합니다! 또한 가장 안쪽 루프 내부에서 수평 합을 수행하는 것은 끔찍한 일입니다. 같은 가장 안쪽의 루프 안에서'result [i] [j]'에 대한 모든 계산을한다면'+ ='가 아니라'result = hsum (vR)'을 수행하십시오. 여기서 hsum은 비 MSVC에 이식 할 수있는 수평 합 함수입니다 (문제가있는 경우). 그리고 작성자가 작성한 것보다 컴파일러가 생성하는 것보다 적습니다. http://stackoverflow.com/questions/6996764/fastest-way-to-do-horizontal-float-vector-sum-on-x86을 참조하십시오. 여기서 나의 대답은 정수 hsum을 언급합니다. –