2016-12-01 2 views
10

짧은 질문은 두 벡터를 사용하는 함수가있는 경우입니다. 하나는 입력이고 다른 하나는 출력됩니다 (별명 없음). 그 중 하나만 정렬 할 수 있습니다. 어느 것을 선택해야합니까?정렬되지 않은로드 대 정렬되지 않은 저장소

더 긴 버전은

void func(size_t n, void *in, void *out) 
{ 
    __m256i *in256 = reinterpret_cast<__m256i *>(in); 
    __m256i *out256 = reinterpret_cast<__m256i *>(out); 
    while (n >= 32) { 
     __m256i data = _mm256_loadu_si256(in256++); 
     // process data 
     _mm256_storeu_si256(out256++, data); 
     n -= 32; 
    } 
    // process the remaining n % 32 bytes; 
} 

, 기능을 고려한다는 것입니다 inout 정렬 32 바이트 인 경우에, vmovdqu를 사용하는 대신 vmovdqa의 수수료가 없습니다. 최악의 시나리오는 둘 다 정렬되지 않고 4 개의로드/저장 중 하나가 캐시 라인 경계를 통과한다는 것입니다.

이 경우 루프에 들어가기 전에 몇 가지 요소를 먼저 처리하여 캐시 선 경계에 정렬 할 수 있습니다. 그러나 문제는 내가 선택해야하는 것인가? 정렬되지 않은로드와 저장소 사이에서 어느 것이 더 나쁩니 까?

+3

memcpy 구현을 살펴보십시오. 나는 평범한 방법이 있다고 생각하지만 그것이 어떤 것인지를 잊어 버린다. 어쩌면 당신이하는 일에 달려 있겠지만. 정렬 된로드는 캐시 라인 경계를 피할 수 있으므로로드 사용 대기 시간 패널티가 발생하지 않습니다 (포인터 증가가 예측 가능한 경우 관련이 없습니다. 왜냐하면 OOO는 루프의 나머지 부분보다 훨씬 앞서로드 주소를 준비 할 수 있기 때문입니다). 객체 외부에서 읽는 것은 종종 안전하지만 작성은 그렇지 않으므로 정리 루프에 대한 전체 스칼라 버전을 피할 수 있다면 결정에 영향을 미칠 수 있습니다. –

+0

필자는 잠시 동안이 테스트를 실시한 결과 적어도 테스트 한 프로세서 (Pentium 4, Core 2, Sandy Bridge 및 Haswell)에서 입력 벡터를 정렬하는 것이 출력 벡터를 정렬하는 것보다 현저히 빠르다고 판단했습니다 . 귀하의 마일리지가 다를 수 있습니다. 더 이상 테스트 코드를 작성하지 않았기 때문에 테스트 코드를 작성하고 테스트를 다시 수행 할 필요가 없으며 모든 종류의 문서를 가리킬 수있는 공식 참조가 없기 때문에이 질문을 대답으로 게시하는 것이 쉽지 않습니다. 그래서 upvote 대신에! :-) –

+0

@CodyGray 고마워요. 나는이 문제에 대한 몇 가지 테스트를 해왔다. 지금까지 내가 말할 수있는 것은 단지 "그것이 달렸어"라는 것입니다. –

답변

0

명백한 이유는 다음과 같습니다. "실제 코드와 실제 데이터를 모두 벤치 마크해야합니다"를 제외하고는 "정답"이 없습니다. 어떤 변형이 더 빠른지 빠르게 사용하는 CPU, 각 패키지에서 수행하는 계산량 및 기타 많은 것들에 크게 의존합니다.

주석에서 언급했듯이 비 일시적인 상점도 사용해보십시오. 당신이하고있는 계산을 피할 데이터 대기 시간이있는 경우

__m256i next = _mm256_loadu_si256(in256++); 
for(...){ 
    __m256i data = next; // usually 0 cost 
    next = _mm256_loadu_si256(in256++); 
    // do computations and store data 
} 

, 당신은 또한 인터리브 두 패키지를 계산 고려해야한다 : 무슨 일이 때로는 도움 즉, 전류 루프 내부에 다음과 같은 데이터 패킷의 입력을로드하는 것입니다 (이것은 두 배의 레지스터를 사용합니다).

관련 문제