2017-01-14 15 views
1

저는 이제 SIMD를 배우고 컴파일러가 내 코드를 더 잘 최적화 할 수있는 방법을 생각하고 있습니다. 이제 Visual C++ 2013 x86을 사용하고 있습니다. 오버레이되지어떻게하면 VC 컴파일러가 SIMD로 내 코드를 최적화 할 수 있을까요?

void computeSum(float* __restrict arr, float* __restrict inp1, float* __restrict inp2, int count) 
{ 
    __declspec(align(16)) float* p1 = inp1; 
    __declspec(align(16)) float* p2 = inp2; 
    __declspec(align(16)) float* ret = arr; 

    while (count > 0) 
    { 
     ret[0] = p1[0] + p2[0]; 
     ret[1] = p1[1] + p2[1]; 
     ret[2] = p1[2] + p2[2]; 
     ret[3] = p1[3] + p2[3]; 

     p1 += 4; 
     p2 += 4; 
     ret += 4; 

     count -= 4; 
    } 
} 

을 내가 배열은 16 바이트 경계 누구나 ​​정렬됩니다 컴파일러를 말하고 싶은 :

내가 배열을 가지고, 나는 다른 배열을 가지고, 나는 다음과 같이 계산하려면 하나의 루프는 4 개의 연속 부동 소수점 합계를 계산합니다.

그러나 생성 된 코드에서 VC는 MOVSS/ADDSS보다 선호하며 ADDPS를 사용하지 않습니다.



프로젝트를 LLVM-vs2013 툴 체인을 사용하도록 구성하면 ADDPS를 사용하여 합계를 계산합니다.

나는 컴파일러 내장 함수를 사용하여 SIMD 코드를 작성하는 방법을 알고 있지만 그게 내가 원하는 것은 아니다.

VC가 ADDPS 명령어를 사용해야한다는 힌트가 더 있습니까?



이것은 전체 코드입니다.

#include <stdio.h> 
#include <stdlib.h> 

void computeSum(float* __restrict arr, float* __restrict inp1, float* __restrict inp2, int count) 
{ 
    __declspec(align(16)) float* p1 = inp1; 
    __declspec(align(16)) float* p2 = inp2; 
    __declspec(align(16)) float* ret = arr; 

    while (count > 0) 
    { 
     ret[0] = p1[0] + p2[0]; 
     ret[1] = p1[1] + p2[1]; 
     ret[2] = p1[2] + p2[2]; 
     ret[3] = p1[3] + p2[3]; 

     p1 += 4; 
     p2 += 4; 
     ret += 4; 

     count -= 4; 
    } 
} 

int main() 
{ 
    float* inp1 = (float*)_aligned_malloc(sizeof(float) * 128, 16); 
    float* inp2 = (float*)_aligned_malloc(sizeof(float) * 128, 16); 
    float* result = (float*)_aligned_malloc(sizeof(float) * 128, 16); 

    for (int i = 0; i < 128; ++i) 
    { 
     inp1[i] = inp2[i] = i; 
    } 

    computeSum(result, inp1, inp2, 128); 

    for (int i = 0; i < 128; ++i) 
    { 
     printf("%f\t", result[i]); 
    } 

    return 0; 
} 
+0

/arch : SSE (또는 이와 유사)를 지정 했습니까? – harold

+0

@harold 예 스위치/arch : SSE2가 사용 가능합니다. – Sorayuki

+0

루프를 풀지 * 않으려 고 시도 했습니까? –

답변

1
비주얼 C++ 2013

이상은 x86 용 /arch:SSE2 사용하는 기본 설정됩니다,하지만 당신은 여전히 ​​명시 적으로 다른 것으로 설정되어 있지 않은 확인하기 위해 비주얼 스튜디오 프로젝트의 설정을 확인해야합니다. x64의 경우 /arch:SSE2이 암시 적입니다.

Visual C++에서 단일 레인 (ADDSS) 지침 대신 다중 레인 (예 : ADDPS)을 자동으로 생성하는 유일한 방법은 자동 벡터화 기 때문입니다. 자세한 내용은 MSDN을 참조하고 스위치 /Qvec-report:2에 특히주의하십시오. 디버그 구성에서 일반적인 것처럼 최적화가 비활성화 된 경우에는 발생하지 않습니다.

대부분의 SIMD (다중 레인) codegen은 명시 적 intrinsics 사용으로 더 잘 수행됩니다. 이 코딩 스타일에 대한 많은 예제는 DirectXMath을 참조하십시오.

+0

보고서를 사용하려면 "자동 벡터 라이저"라는 매개 변수 스위치를 사용하는 것이 중요합니다. 그러나 몇 가지 시도 후에 나는 여전히 옵티마이 저가 addps를 사용할 수 없습니다. 샘플 코드를 제공해 주시겠습니까? 고맙습니다 – Sorayuki