2013-11-23 3 views
1

내가 가진 아주 잠시 동안 저를 도청 한 한 가지입니다 트리플위한 동료와 같은 루프 :x86 명령어의 논 블로킹 메모리 쓰기? 내가 여기에 몇 가지 고도로 최적화 된 코드를 작성하고 있어요

for(int ii = 0; ii < ny; ii++){ 
    for(int jj = 0; jj < nx; jj++){ 
     ....some serious calculation.... 
     for(int kk = 0; kk < CONSTANT; kk++){ 
      _mm_storeu_ps(&((cells.dir[kk])[ii * nx +jj],result); // Writing result to correct location 
     } 
    } 
} 

세포는 9 포인터의 단지 구조체입니다, 각각은 큰 크기의 배열을 가리킨다. 이 코드는 원래 구조체 (AoS) 모드의 배열로 작성되었으므로 배열의 구조체를 사용하기 위해 모든 것을 수동으로 다시 작성하므로 속도를 높이기 위해 SSE를 사용할 수 있습니다. 그러나 코드의 원래 구조로 인해 위의 코드는 결과를 캐시에 친숙하지 않은 방식으로 올바른 위치에 써야합니다. 그 라인을 주석 처리하면 전체 프로그램의 실행 시간이 40 % . 난 그냥 활용할 수있는 x86 용 비 차단 메모리 쓰기 명령어가 있다면 궁금해? 아니면 내가이 메모리로 쓸 수있는 다른 트릭이나? 루프의 구조를 변경하라는 제안을하지 마십시오. 너무 많은 시간이 소요됩니다.

감사합니다, 밥

+2

거의 모든 최신 비 내장 프로세서의 기록은 이미 비 차단입니다. 그들은 단지 대기열에 밀려 들어가 백그라운드에서 수행됩니다. 즉, 차단되기 전에 대기열의 크기에 제한이 있습니다. 즉, 캐시 라인 사용 방법도 알고 있어야합니다. – Mysticial

+0

@Mysticial 나는''_ _ _ _ _ _ _ _ _ _ _ _ _ _''이 캐시 미스보다 프로그램 비용이 매우 비싸기 때문에 가능성이 더 높습니다. 의견 있으십니까? – dorafmon

+0

@dorafmon : 정확한 메모리 위치에 결과가 필요합니까? 아니면 계산을 위해 나중에 다시 읽으려고합니까? 캐시에보다 친숙한 방법으로 임시 버퍼에 쓰면 성능을 향상시킬 수 있습니다. 나는 과거에 성공을 거두었 다. 그러나 출력 배열에서 특정 순서로 있어야하는 최종 결과를 얻으려는 상점이 있다면 운이 좋지 않을 수 있습니다. –

답변

1

항을 참조 Agner 안개 설명서 optimizing cpp에서 9.11 명시 캐시 제어. 특히 내장형 _mm_stream_pi을 사용하여 캐시 라인을 읽지 않고 쓰기를 수행하는 방법을 보여주는 99 페이지의 예제 9.6b (아래에 게시 됨)를 살펴보십시오. 나는 아직 시도하지 않았지만 조사할만한 가치가있다. 이것은 행렬 크기가 임계 보폭의 배수 일 때 도움이됩니다. 그러나 더 나은 해결책은 코드를 변경하고 루프 타일링을 사용하는 것입니다 (예제 9.5b 참조). 그러나 루프의 구조를 변경하지 않으려 고 _mm_stream_ps을 사용하는 것이 가장 좋은 방법 일 수 있다고 말했을 것입니다.

// From Agner Fog's manual optimizing cpp on page 99 
// Example 9.6b 
#include "xmmintrin.h" // header for intrinsic functions 
// This function stores a double without loading a cache line: 
static inline void StoreNTD(double * dest, double const & source) { 
    _mm_stream_pi((__m64*)dest, *(__m64*)&source); // MOVNTQ 
    _mm_empty(); // EMMS 
} 
const int SIZE = 512; // number of rows and columns in matrix 
// function to transpose and copy matrix 
void TransposeCopy(double a[SIZE][SIZE], double b[SIZE][SIZE]) { 
    int r, c; 
    for (r = 0; r < SIZE; r++) { 
     for (c = 0; c < SIZE; c++) { 
      StoreNTD(&a[c][r], b[r][c]); 
     } 
    } 
}