2016-07-19 7 views
2

4 개의 배정도 값이있는 AVX 레지스터가 있습니다. 이제는 각 요소마다 개별적으로 연산을 수행해야합니다. 내가해야 할 일의 정리는 다음과 같다.AVX 레지스터의 불법 콘텐츠

Situation: 
    a = [a4 a3 a2 a1] 
    w = [ 0 0 0 w1] 
    x = [ 0 0 0 x1] 
    y = [ 0 0 0 y1] 
    z = [ 0 0 0 z1] 

Desired result: 
    w = [-- -- -- w1+a1] 
    x = [-- -- -- x1+a2] 
    y = [-- -- -- y1+a3] 
    z = [-- -- -- z1+a4] 

원하는 결과를 제외하고는 두 값의 합계가 아니라 더 복잡한 산술 표현식을 사용합니다. 내가 --을 넣었을 때, 나는 버려 질 그 값들을 신경 쓰지 않는다는 것을 의미합니다.

순열 연산을 사용하여 a 레지스터를 순열 할 수 있다고 생각했습니다 (예 : Reverse a AVX register containing doubles using a single AVX intrinsic 참조). 내 유일한 문제는 이러한 작업을 동적으로 수행해야하는 동안 이러한 내장 함수에는 즉각적인 즉, 컴파일 타임 값이 필요하다는 것입니다.

나는 _mm256_permutevar_pd 같은 다른 레지스터에 포함 된 정수에서 작동 순열 내장 함수를 찾았지만, 그것은 처음부터 a3에게 무엇을 할. 수있는 유일한 방법이이 지침을 사용하는 것은 불가능하다 예를 들어, 그들 중 누구도 (차선을 가로 질러 뒤 바꿔 없다 이 지시 사항을 사용하여 내가 원하지 않는 if을 사용하는 것이 좋습니다. if 조건을 따르는 128 비트 레인에서 순열을 수행하고 차선에서 동적 순열을 수행해야합니까? 아니면 더 나은 해결책이 있습니까? ? 성능 및 유지 보수성 모두에 관심이 있습니다. 최대 AVX2 지침을 사용할 수 있습니다. 어셈블리 옵션이지만 instrinsics 선호 할 것입니다.

+1

메모리에 벡터로 저장하고 다시 스칼라로 읽으시겠습니까? –

+0

그런 솔루션에서 멀어 질 때마다 응용 프로그램에서 막 속도가 빨라졌습니다. 이미 "저장소에 메모리"솔루션을 구현했습니다. 이제 전체 작업이 레지스터에서 수행 될 때 차이점을보고 싶습니다. – Spiros

+0

결과가 4 개의 별도 스칼라 복식으로 필요합니까? (다른 요소가없는 벡터의 낮은 요소에서 다루는 것과 같은 것입니다). 비 컴파일 타임 상수 셔플은 어디서 들어 옵니까? 나는 왜 단지 'vextractf128'로 풀고,'__m128d'의 상위 절반을'vmovhlps' 또는 무엇인가로 스칼라 double에 넣을 수없는 이유를 모르겠습니다. 어떤 벡터 요소가 어떤 변수 이름을 가지고 있는지 알고 있습니다 ... –

답변

1

[ z y x w ]을 벡터로 포장 한 후 +이 나타내는 것이 무엇이든 SIMD 연산을 사용하여 표현할 수 있습니다. 가되고 있기 때문에

void unpack_256_to_scalar(__m256d a) { 
    // unpack to two 128b halves 
    __m128d a01 = _mm256_castpd256_pd128(a); // extractf128_pd(a, 0) should also compile the same way, if you like more-consistent C instead of code that matches the asm you expect 
    __m128d a23 = _mm256_extractf128_pd(a, 1); 

    // and then halves of each 128b vector 
    double a0 = _mm_cvtsd_f64(a01); 
    double a1 = _mm_cvtsd_f64(_mm_unpackhi_pd(a01,a01)); 
    double a2 = _mm_cvtsd_f64(a23); 
    double a3 = _mm_cvtsd_f64(_mm_unpackhi_pd(a23,a23)); 
    ... 
    // use the results 
} 

compiles (on the Godbolt compiler explorer) GCC 만 세 그 소리와 지침, 또는 4 : 그러나하지 않을 경우 :

추출 4 개 요소 당신이 원하는 무엇이든 할 다음 double의 정상적인 방법을 스칼라, 및하기 레지스터 할당을 통한 바보 :

unpack_256_to_scalar(double __vector(4)): 
    vextractf128 xmm1, ymm0, 0x1 
    vunpckhpd  xmm2, xmm0, xmm0 
    vmovapd xmm3, xmm1     # gcc should have use vunpckhpd xmm3, xmm1,xmm1. This wasted mov is a missed-optimization bug. 
    vunpckhpd  xmm1, xmm1, xmm1 
    # the empty asm statement emitted the empty string here. 
    vzeroupper 
    ret 

각 3 개의 명령어는 벡터 결과의 하위 요소와 다른 요소를 생성합니다. 어떤 상수 (내가 unpackhi_pd 대신 shufpd하거나 데이터 이동의 내부 표현에서 셔플을 생성 할 때 그 소리가 사용 vpermilpd의 선택 이유입니다.), 심지어 즉치 상수를 필요하지 않습니다

는 필요 가변 셔플을 사용하여 제어 마스크로 사용되는 벡터는 여기서 미친 듯합니다. 이것에 관한 어떤 것도 동적/가변 셔플이나 추출이 필요하지 않습니다.

BTW의 고성능 코드 작성에 대한 링크는 태그 위키를 참조하십시오.