2014-04-22 3 views
1

잘못 정렬 최적화하기 위해 노력하고 있지만 내 유한 차이 코드에 필요한 읽기, I는 다음과 같이 정렬되지 않은 부하를 변경 :이에일부 CPU에서는 SSE가 정렬되지 않은 읽기보다 느리게 정렬되고 셔플이되는 이유는 무엇입니까?

__m128 pm1 =_mm_loadu_ps(&H[k-1]); 

가 + 셔플 읽어 정렬 코드 : H는 16 바이트입니다

__m128 p0 =_mm_load_ps(&H[k]); 
__m128 pm4 =_mm_load_ps(&H[k-4]); 
__m128 pm1 =_mm_shuffle_ps(p0,p0,0x90); // move 3 floats to higher positions 
__m128 tpm1 =_mm_shuffle_ps(pm4,pm4,0x03); // get missing lowest float 
     pm1 =_mm_move_ss(pm1,tpm1);  // pack lowest float with 3 others 

, - 정렬; H[k+1], H[k±3]movlhps & movhlpsH[k±2] (here의 전체 루프 코드)에 대한 유사한 변경이있었습니다.

내 코어 i7-930에서 H[k±3] 읽기가 최적화 된 것으로 나타 났으며 ±1에 다음 최적화를 추가하면 백분율 단위로 속도가 느려집니다. ±1±3 사이에서 전환해도 결과는 바뀌지 않았습니다.

동시에 코어 2 - 6300 듀오 및 코어 2 쿼드에서 두 가지 최적화 (±1±3)를 사용하면 성능이 향상되고 (수십 %) 코어 i7-4765T의 경우 성능이 저하됩니다 퍼센트 단위).

펜티엄 4에서 movlhps/movhlps을 포함하여 불일치 읽기를 최적화하려고하면 모든 속도가 느려집니다.

왜 CPU마다 다른가? 코드 크기가 커지기 때문에 루프가 일부 명령어 캐시에 맞지 않을 수 있습니까? 또는 일부 CPU는 잘못 정렬 된 읽기에 민감하지 않고 다른 일부는 훨씬 더 민감하기 때문에 그럴 수 있습니까? 또는 셔플 같은 동작이 일부 CPU에서 느릴 수 있습니까?

+1

'movhlps','shufps','movaps reg, reg'까지 모두 P4에서 느립니다. 끔찍하다. 나는 P4가 존재하지 않았으며 Core2 이상에 초점을 맞추었다. – harold

답변

2

오래된 CPU의 경우 잘못 정렬 된로드는 성능상 큰 불이익을 낳습니다. 두 개의 버스 읽기 사이클을 생성 한 다음 두 개의 읽기 사이클 후에 몇 가지 추가 수정이 이루어집니다. 즉, 정렬되지 않은로드는 일반적으로 정렬 된로드보다 2 배 이상 느립니다. 그러나보다 최근의 CPU (예 : 코어 i7)에서는 잘못 정렬 된 부하에 대한 패널티가 거의 무시할 수 있습니다. 따라서 오래된 CPU와 새로운 CPU를 지원해야한다면, 각각에 대해 잘못 정렬 된로드를 다룰 수 있습니다.

+0

하지만 잘못 정렬 된로드는 펜티엄 4에서 정렬 된로드 + 셔플보다 빠르다고 생각합니다. – Ruslan

+0

네, 왜 펜티엄 4로 그 효과를보고 있는지 모르겠습니다. 다른 명령어의 대기 시간을 비교하여 정렬되지 않은로드의 2-3 사이클 비용과 비교할 필요가 있습니다. –

4

2 년마다 인텔은 새로운 마이크로 아키텍처를 출시합니다. 실행 단위 수가 변경 될 수 있으며, 이전에 하나의 실행 단위에서만 실행할 수있는 명령은 최신 프로세서에서 2 또는 3 개를 사용할 수 있습니다. shuffle 실행 장치가 추가 될 때와 같이 명령 대기 시간이 변경 될 수 있습니다.

인텔은 최적화 관련 참조 설명서에서 다음과 같은 링크를 사용하여 관련 섹션을 복사했습니다.

http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf

3.5.2.7 부동 소수점/SIMD 피연산자

메모리 명령에서 MOVUPD 두 개의 64 비트 부하를 수행하지만 어드레스를 조절하고 결합하는 추가적인 μops을 필요 단일 레지스터에로드됩니다. 이 동일한 기능은 MOVSD XMMREG1, MEM을 사용하여 얻을 수 있습니다. MOVSD XMMREG2, MEM + 8; UNPCKLPD XMMREG1, XMMREG2는 더 적은 수의 μops를 사용하며 추적 캐시에보다 효과적으로 패키징 할 수 있습니다. 후자의 대안은 경우에 따라 수 퍼센트의 성능 향상을 제공하는 것으로 밝혀졌습니다.그 인코딩은 더 많은 명령 바이트를 필요로하지만, 이것은 거의 펜티엄 4 프로세서에서 문제가되지 않습니다. MOVUPD의 상점 버전은 복잡하고 느리므로 두 MOVSD 및 UNPCKHPD가있는 순서가 항상 사용되어야합니다.

조립/컴파일러 (128) 대신에 정렬되지 않은 비트 부하 MOVUPD XMMREG1, MEM을 사용하여 규정 44 (ML 충격, 보편성 L)을 부호화, MOVSD XMMREG1, MEM을 사용; MOVSD XMMREG2, MEM + 8; UNPCKLPD XMMREG1, XMMREG2. 추가 레지스터를 사용할 수없는 경우 MOVSD XMMREG1, MEM을 사용하십시오. MOVHPD XMMREG1, MEM + 8.

조립/컴파일러 코딩 규칙 45 (M에 미치는 영향, ML 일반성) 대신 MOVSD MEM, XMMREG1를 사용 MOVUPD MEM, 상점에 대한 XMMREG1를 사용하는; UNPCKHPD XMMREG1, XMMREG1; 대신 MOVSD MEM + 8, XMMREG1. 의 AoS 형식으로 SOA에서

섹션 6.5.1.2 데이터 스위 즐링

스위 즐링 데이터는 3D 형상, 비디오 및 이미지 등을 포함한 응용 프로그램 도메인의 숫자에 적용 할 수 있습니다. 부동 소수점 및 정수 데이터를 처리하기 위해 두 가지 다른 스위 즐 기법을 적용 할 수 있습니다. 예제 6-3에서는 SHUFPS, MOVLHPS, MOVHLPS 명령어를 사용하는 swizzle 함수를 보여줍니다. enter image description here

enter image description here

예 6-3 (로딩 SHUFPS 및 XMM 레지스터 복사 절반을 사용하여 16 바이트)의 기술은 각각의 적재 반쪽의 다른 방법을 통해 바람직

새로운 마이크로 아키텍쳐에서 MOVLPS/MOVHPS를 사용하는 벡터. MOVLPS/MOVHPS를 사용하여 8 바이트를로드하면 코드 종속성이 생기고 실행 엔진의 처리량이 줄어들 수 있기 때문입니다. 예제 6-3과 예제 6-4의 성능 고려 사항은 종종 각 마이크로 아키텍처의 특성에 따라 달라집니다. 예를 들어 인텔 코어 마이크로 아키텍처에서 SHUFPS를 실행하는 경향이 PUNPCKxxx 명령보다 느려지는 경향이 있습니다. 향상된 인텔 코어 마이크로 아키텍처에서 SHUFPS 및 PUNPCKxxx 명령은 모두 128 비트 셔플 실행 장치로 인해 1 사이클 처리량으로 실행됩니다. 다음 중요한 고려 사항은 PUNPCKxxx 대 MOVLHPS/MOVHLPS를 실행할 수있는 단 하나의 포트가 여러 포트에서 실행할 수 있다는 것입니다. 두 기술의 성능은 SIMD 명령어 실행을위한 3 개의 포트로 인해 이전 마이크로 아키텍처에 비해 인텔 코어 마이크로 아키텍처가 향상되었습니다. 두 기술 모두 128 비트 셔플 유닛으로 인해 향상된 인텔 코어 마이크로 아키텍처를 더욱 향상시킵니다.