좋아, 그래서이 코드가 무슨 일을하는지 모르겠다.하지만 ternery 연산자를 최적화하고 SSE에서만 작동하는이 코드 부분을 얻는 방법을 묻는 것을 알고있다. 첫 번째 단계로 조건부 연산자를 피하기 위해 정수 플래그와 곱셈을 사용하는 접근 방식을 시도하는 것이 좋습니다. 예를 들어 :
는
이 섹션
for(int m=0; m < PBS_SSE_PIXELS_PROCESS_AT_ONCE; m++)
{
bool bIsEvenFloor = vn1.m128i_u16[m]==0;
vnPxChroma.m128i_u16[m] = m%2==0 ?
(bIsEvenFloor ? vnPxCeilChroma.m128i_u16[m] : vnPxFloorChroma.m128i_u16[m]) :
(bIsEvenFloor ? vnPxFloorChroma.m128i_u16[m] : vnPxCeilChroma.m128i_u16[m]);
}
는 시리얼 메모리 액세스의 성능 향상을 잃게되지만 모듈로 연산과 두 개의 드롭 두 개의 루프로 분할하여 기본적으로이
// DISCLAIMER: Untested both in compilation and execution
// Process all m%2=0 in steps of 2
for(int m=0; m < PBS_SSE_PIXELS_PROCESS_AT_ONCE; m+=2)
{
// This line could surely pack muliple u16s into one SSE2 register
uint16 iIsOddFloor = vn1.m128i_u16[m] & 0x1 // If u16[m] == 0, result is 0
uint16 iIsEvenFloor = iIsOddFloor^0x1 // Flip 1 to 0, 0 to 1
// This line could surely perform an SSE2 multiply across multiple registers
vnPxChroma.m128i_u16[m] = iIsEvenFloor * vnPxCeilChroma.m128i_u16[m] +
iIsOddFloor * vnPxFloorChroma.m128i_u16[m]
}
// Process all m%2!=0 in steps of 2
for(int m=1; m < PBS_SSE_PIXELS_PROCESS_AT_ONCE; m+=2)
{
uint16 iIsOddFloor = vn1.m128i_u16[m] & 0x1 // If u16[m] == 0, result is 0
uint16 iIsEvenFloor = iIsOddFloor^0x1 // Flip 1 to 0, 0 to 1
vnPxChroma.m128i_u16[m] = iIsEvenFloor * vnPxFloorChroma.m128i_u16[m] +
iIsOddFloor * vnPxCeilChroma.m128i_u16[m]
}
문법적으로 동일합니다 조건부 연산자.
이제 루프 당 두 개의 부울 연산자와 추가 할 수있는 곱셈 이 있음을 알게됩니다. 내 고유 구현 SSB는이 아닙니다. vn1.m123i_u16 [] 어레이에 저장된 내용은 무엇입니까? 단지 0과 1이 맞습니까? 그렇다면이 부분이 필요 없으므로이 부분을 없앨 수 있습니다. 그렇지 않다면이 배열의 데이터를 정규화하여 0과 1 만 가질 수 있습니까? vn1.m123i_u16 배열은 다음과 0이 포함되어있는 경우이 코드는 또한 내가 SSE는 isEvenFloor * vnPx... part
을 수행 할 수없고 iIsEvenFloor
및 iIsOddFloor
레지스터를 저장하는 곱 사용하지 않는 알 수
uint16 iIsOddFloor = vn1.m128i_u16[m]
uint16 iIsEvenFloor = iIsOddFloor^0x1 // Flip 1 to 0, 0 to 1
된다. 죄송합니다. u16에 대한 SSE 내장 함수를 기억할 수 없지만,이 방법이 도움이되기를 바랍니다. 당신이 게시 한, 내 수정, 우리는 여전히 SSE1/2/3 내장 함수의 전체를 사용을하지 않는 코드의이 섹션에서는
// This line could surely pack muliple u16s into one SSE2 register
uint16 iIsOddFloor = vn1.m128i_u16[m] & 0x1 // If u16[m] == 0, result is 0
uint16 iIsEvenFloor = iIsOddFloor^0x1 // Flip 1 to 0, 0 to 1
// This line could surely perform an SSE2 multiply across multiple registers
vnPxChroma.m128i_u16[m] = iIsEvenFloor * vnPxCeilChroma.m128i_u16[m] +
iIsOddFloor * vnPxFloorChroma.m128i_u16[m]
하지만 몇 가지 포인트를 제공 할 수 있습니다 : 일부 최적화 당신은에 보일 것입니다 (코드를 벡터화하는 방법).
마지막으로 나는 모든 것을 테스트한다고 말할 것입니다. 변경 및 프로파일 링을 다시하기 전에 위의 코드를 변경하지 않고 실행하십시오.실제 성능 수치는 당신을 놀라게 할 수 있습니다!
업데이트 1 : 나는 Intel SIMD Intrinsics documentation 겪은
이에 사용 될 수있는 관련 내장 함수를 선택합니다. 구체적으로는 비트 단위 XOR을 살펴보고, 및 __m128i 데이터 형식 여섯 8 비트, 8-16 비트, 네 개의 32- 비트 또는 2 (64)를 수납 할 수 MULT는/
__m128 데이터 형식
담기 비트 정수 값.
__m128i _mm_add_epi16 (__ m128i의 A, __m128i B는)
가 B의 부호 8 또는 부호없는 16 비트 정수로 A의 8 개 부호 또는 부호없는 16 개 비트 정수 추가
__m128i _mm_mulhi_epu16 (__ m128i , __m128i b)
a의 8 개의 부호없는 16 비트 정수에 b의 8- 부호없는 16 비트 정수를 곱합니다. 는 상위 8 부호없는 32 비트 16 비트
R0 = HIWORD (A0의 *의 B0)
R1 = HIWORD (A1에 *를 B1)
R2 = HIWORD (A2의 *의 B2)
결과 팩 R3 = HIWORD (A3의 *의 B3)
..
R7 = HIWORD (A7의 *의 B7)
__m128i _mm_mullo_epi16 (__ m128i의 A, __m128i의 b)
곱 8 부호 또는 부호없는 16 비트 정수에서 a는 8-signed 또는 unsigned 16- b의 정수입니다. 는 상위 16 비트 팩 8 부호 또는 부호없는 32 비트 R0 = LOWORD (A0의 *의 B0)
R1 = LOWORD (A1에 *를 B1)
R2 = LOWORD (A2의 *의 B2)
결과
R3 = LOWORD (A3의 *의 B3)
..
R7 = LOWORD (A7의 *의 B7)
__m128i _mm_and_si128 (__ m128i의 A, __m128i의 b)
은 비트 단위로 수행하고 128 비트의 m1 단위의 값과 m2 단위의 128 비트 값
__m128i _mm_andnot_si128 (__ m128i A는, __m128i B는)
이 비트를 계산하고, (B)의 128 비트 값 NOT A의 128 비트 값의 논리합.
__m128i _mm_xor_si128 (__ m128i의 A, B의 __m128i)
가 m2에서 128 비트 값 M1 (128)의 비트 값의 비트 단위 XOR을 수행한다. 참조
에 대한 코드 예제에서도
UINT16 U1 = U2 = U3 ...= u15 = 0x1
__m128i vnMask = _mm_set1_epi16 (0x0001); // 8 개의 부호있는 16 비트 정수 값을 설정합니다.
UINT16의 VN1 [I] = vnFloors의 [I] &을 0x1
__m128i VN1 = _mm_and_si128 (vnFloors, vnMask); // a의 128 비트 값과 b의 128 비트 값의 비트 단위 AND를 계산합니다.
SSE의 내장 함수는 읽기 어려운 : 그때부터, 나는 솔루션을 최적화하기 위해 SSE 벡터화를 사용할 수 있었다. 이 섹션을 설명하기 위해 몇 가지 의견/동등한 C++ 코드 블록을 추가 하시겠습니까? –
코드에서 수행하고자하는 작업은 무엇입니까? – ronag
나는이 스 니펫 (암호없는 식별자 및 컨텍스트 없음)에 다소 당혹 스럽지만 비교를 곱셈 및 덧셈으로 바꾸지 않는 이유는 무엇입니까? – zrxq