2017-12-06 5 views
0
int MAX_DIM = 100; 
    float a[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); 
    float b[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); 
    float d[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); 
    /* 
    * I fill these arrays with some values 
    */ 

for(int i=0;i<MAX_DIM;i+=1){ 

     for(int j=0;j<MAX_DIM;j+=4){ 

     for(int k=0;k<MAX_DIM;k+=4){ 

      __m128 result = _mm_load_ps(&d[i][j]); 

      __m128 a_line = _mm_load_ps(&a[i][k]); 

      __m128 b_line0 = _mm_load_ps(&b[k][j+0]); 

      __m128 b_line1 = _mm_loadu_ps(&b[k][j+1]); 

      __m128 b_line2 = _mm_loadu_ps(&b[k][j+2]); 

      __m128 b_line3 = _mm_loadu_ps(&b[k][j+3]); 

     result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0x00), b_line0)); 
     result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0x55), b_line1)); 
     result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0xaa), b_line2)); 
     result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0xff), b_line3)); 
     _mm_store_ps(&d[i][j],result); 
     } 
     } 
    } 

SSE를 사용하여 행렬 곱셈을 만들었습니다. 코드는 흐름으로 실행됩니다. 행에서 4 개의 요소를 취하여 b의 열에서 4 개의 요소로 곱한 후 다음 열의 4 개 요소로 이동하여 열 b의 다음 4 개 요소로 이동SSE 내장 함수를 사용하는 크기 100 * 100의 행렬

오류가 발생합니다.

내가 우분투에 GCC 5.4.0을 사용하는 이유 Segmentation fault (core dumped) 난 정말 모르는 16.04.5

편집 : 분할 오류가 _mm_loadu_ps 에 의해 해결되었다 또한 내가 만약 greatfull 될 것입니다 논리에 문제가있다 누군가 나를 찾을 수 있도록 도와줍니다.

+0

Linux에서 GCC를 사용하고있는 것 같습니다. 다음 정보로 게시물을 업데이트하십시오. a) OS, b) 컴파일러 및 버전, c) gdb에서 실행 (해당되는 경우)하고 스택 추적을 복사/붙여 넣기하십시오. – paulsm4

+2

로드 중 일부 (마지막 세 개)의 정렬이 잘못되었습니다.이 경우 (또는 모든 경우에 대해) '_mm_loadu_ps'를 사용하십시오. –

답변

2
분할 오류가 _mm_loadu_ps에 의해 해결되었다

또한 ... 당신은 b[k][j+0..7]에 4 개 겹치는 창을로드하는

논리에 문제가있다. (이 때문에 loadu이 필요합니다.)

아마 b[k][j+0], +4, +8, +12을로드 할 예정입니까? 그렇다면 b을 64로 맞춰야하므로 4 개의로드가 모두 동일한 캐시 라인 (성능)에서 나옵니다. 스트라이드 액세스는 좋지 않지만 터치 할 때마다 64 바이트의 모든 캐시 라인을 사용하는 것이 행 메이저 대 칼럼 메이저를 스카라 코드에서 완전히 틀리게하는 것보다 훨씬 낫습니다.

은 내가 당신의 텍스트 설명이 당신의 코드를 설명 모르겠어요 b

에서 열 4 개 요소에 의해 곱 a에서 행의 4 개 요소를 가지고.

b을 이미 바꾸어 놓지 않은 한, 메모리에 인접하지 않으므로 SIMD로드로 동일한 열의 값을 여러 개로드 할 수 없습니다.

C 다차원 배열은 "행 장조"입니다. 마지막 색인은 다음 상위 메모리 주소로 이동할 때 가장 빠르게 변하는 색인입니다. _mm_loadu_ps(&b[k][j+1])이 (가) b[k+0..3][j+1]을 (를) 줄 예정이라고 생각 했습니까? 그렇다면,이 SSE matrix-matrix multiplication의 중복 (그 질문은. 32 비트 정수가 아닌 32 비트 부동 소수점,하지만 같은 레이아웃 문제를 사용하여 작업 루프 구조에 대한 것을 참조한다.)


이를 디버깅하려면,이다 값의 간단한 패턴을 b[]에 넣으십시오. 마찬가지로

#include <stdalign.> 

alignas(64) float b[MAX_DIM][MAX_DIM] = { 
    0000, 0001, 0002, 0003, 0004, ..., 
    0100, 0101, 0102, ..., 
    0200, 0201, 0202, ..., 
}; 

// i.e. for (...) b[i][j] = 100 * i + j; 

그런 다음 디버거에서 코드를 단계별로 실행하면 벡터에서 어떤 값이 끝나는 지 확인할 수 있습니다. 당신의 a[][]

, 어쩌면 당신은 (대신 C 변수의) 레지스터에서 찾고 그렇다면 90000.0 + 100 * i + j을 사용하는 당신은 여전히 ​​값이 a을하고 b을있는 어떤 알 수 있습니다.관련


는 :

관련 문제