문제

내 코드베이스의 몇 가지 장소가 큰 데이터 세트에 대해 동일한 작업이 매우 많은 시간을 반복합니다. 경우에 따라 처리하는 데 상당한 시간이 걸립니다.

SSE를 사용하여 이러한 루프를 구현하면 성능을 크게 향상시켜야한다고 생각합니다. 특히 많은 작업이 동일한 데이터 세트에서 수행되는 경우에 데이터가 처음에 캐시에 읽히면 처음에 캐시에 읽히면 캐시가 스톨에 표시되지 않아야한다고 생각합니다. 그것. 그러나 나는 이것에 대해 확실하지 않습니다.

  • SSE 명령을 활용하기 위해 코드를 작성하는 컴파일러 및 OS 독립적 인 방법이 있습니까? SSE 운영을 포함한 VC ++ INTRINSICS를 좋아하지만 크로스 컴파일러 솔루션을 찾지 못했습니다.

  • 나는 여전히 SSE 지원이 없거나 제한적이지 않은 일부 CPU를 지원해야합니다 (예 : Intel Celeron). 프로세스가 시작될 때 실행중인 CPU를 기반으로 기본 또는 SSE 최적화 코드에 연결되는 일종의 "실행 시간 링커"와 같이 다른 버전의 프로그램을 만들지 않아도되는 방법이 있습니까?

  • 다른 인텔과 AMD CPU 쇼의 명령 세트를 살펴보면 다른 CPU 확장 사항은 어떻습니까?

도움이 되었습니까?

해결책

두 번째 지점에는 차이점을 다른 기능으로 분리 할 수있는 한 몇 가지 솔루션이 있습니다.

  • 평범한 오래된 C 함수 포인터
  • 동적 링크 (일반적으로 C 함수 포인터에 의존하는)
  • C ++를 사용하는 경우 다른 아키텍처에 대한 지원을 나타내는 다른 클래스와 가상 기능을 사용하면 이에 큰 도움이 될 수 있습니다.

간접 함수 호출에 의존하기 때문에 다른 작업을 추상화하는 기능은 일반적으로 다소 높은 레벨 기능을 나타내거나 호출 오버 헤드의 최적화 된 명령에서 얻은 모든 이익을 잃을 수 있습니다 (즉, Don '). t 개별 SSE 운영을 추상화합니다 - 당신이하고있는 일을 추상화하십시오).

다음은 기능 포인터를 사용하는 예입니다.

typedef int (*scale_func_ptr)( int scalar, int* pData, int count);


int non_sse_scale( int scalar, int* pData, int count)
{
    // do whatever work needs done, without SSE so it'll work on older CPUs

    return 0;
}

int sse_scale( int scalar, in pData, int count)
{
    // equivalent code, but uses SSE

    return 0;
}


// at initialization

scale_func_ptr scale_func = non_sse_scale;

if (useSSE) {
    scale_func = sse_scale;
}


// now, when you want to do the work:

scale_func( 12, theData_ptr, 512);  // this will call the routine that tailored to SSE 
                                    // if the CPU supports it, otherwise calls the non-SSE
                                    // version of the function

다른 팁

주제에 대한 좋은 독서 : 지시 설정 전쟁을 중지하십시오

짧은 개요 : 죄송합니다. 단순하고 가장 호환되는 (인텔 대 AMD) 방식으로 문제를 해결할 수 없습니다.

SSE 내입는 Visual C ++, GCC 및 인텔 컴파일러와 함께 작동합니다. 요즘 사용하는 데 아무런 문제가 없습니다.

SSE를 사용하지 않는 코드 버전을 항상 유지하고 SSE 구현에 대해 지속적으로 확인해야합니다.

이는 디버깅에 도움이 될뿐만 아니라 필요한 SSE 버전을 지원하지 않는 CPU 또는 아키텍처를 지원하려면 유용합니다.

귀하의 의견에 대한 답변으로 :

효과적으로, 실제로 지원되지 않는 지침이 포함 된 코드를 실행하려고하지 않는 한 괜찮습니다. "If (see2supported) {...} else {...}"유형 스위치를 사용하여 도망 갈 수 있습니다.

의존합니다. SSE 지침이 실행되지 않는 한 바이너리에 존재하는 것은 좋습니다. CPU는 문제가 없습니다.

그러나 컴파일러에서 SSE 지원을 활성화하면 SSE 등가물 (예 : Scalar Floating-Point Ops 등)에 대한 여러 "일반"지침을 교환 할 가능성이 높으므로 일반 비 SSE 코드의 덩어리조차도 폭발합니다. 지원하지 않는 CPU에서.

따라서 SSE가 활성화 된 상태에서 개별적으로 또는 두 개의 파일을 별도로 컴파일 할 가능성이 높으며 모든 SSE 루틴을 포함 할 수 있습니다. 그런 다음 SSE 지원없이 컴파일되는 나머지 앱과 연결하십시오.

스칼라 코드에 대한 대체 SSE 구현을 손으로 코딩하는 대신 Opencl. 계산 집약적 인 응용 프로그램을위한 공급 업체 중립 휴대용 크로스 플랫폼 시스템입니다 (그리고 유행어를 준수합니다!). 벡터화 된 작업을 위해 설계된 C99의 하위 집합에 알고리즘을 작성할 수 있으며, 이는 SSE보다 훨씬 쉽습니다. 무엇보다도 OpenCL은 런타임에 최상의 구현을 생성하여 GPU에서 실행합니다. 또는 CPU에서. 기본적으로 SSE 코드를 작성합니다.

내 코드베이스의 몇 가지 장소가 큰 데이터 세트에 대해 동일한 작업이 매우 많은 시간을 반복합니다. 경우에 따라 처리하는 데 상당한 시간이 걸립니다.

응용 프로그램은 OpenCL이 해결하도록 설계된 문제의 종류처럼 들립니다. SSE에 대체 기능을 작성하면 실행 속도를 확실히 향상시킬 수 있지만 작성 및 디버그는 많은 작업입니다.

SSE 명령을 활용하기 위해 코드를 작성하는 컴파일러 및 OS 독립적 인 방법이 있습니까? SSE 운영을 포함한 VC ++ INTRINSICS를 좋아하지만 크로스 컴파일러 솔루션을 찾지 못했습니다.

예. SSE 내부는 Intel에 의해 본질적으로 표준화되었으므로 Windows, Linux 및 Mac (특히 Visual C ++ 및 GNU G ++) 사이에서 동일한 기능이 동일하게 작동합니다.

나는 여전히 SSE 지원이 없거나 제한적이지 않은 일부 CPU를 지원해야합니다 (예 : Intel Celeron). 프로세스가 시작될 때 실행중인 CPU를 기반으로 기본 또는 SSE 최적화 코드에 연결되는 일종의 "실행 시간 링커"와 같이 다른 버전의 프로그램을 만들지 않아도되는 방법이 있습니까?

당신은 그렇게 할 수 있습니다 (예 : 사용 dlopen()) 그러나 그것은 매우 복잡한 해결책입니다. CPU에 따라 함수 인터페이스를 정의하고 함수 포인터를 통해 또는 C ++를 통해 최적화 된 기능의 적절한 버전을 호출하는 것이 훨씬 간단합니다.

OpenCL을 사용하면 주어진 아키텍처의 런타임에 코드가 생성되므로이를 수행 할 필요는 없습니다.

다른 인텔과 AMD CPU 쇼의 명령 세트를 살펴보면 다른 CPU 확장 사항은 어떻습니까?

SSE 명령 세트 내에는 많은 맛이 있습니다. 특정 지침이 없을 때 SSE의 다른 서브 세트에서 동일한 알고리즘을 코딩하는 것은 매우 어려울 수 있습니다. SSE2와 같은 최소 지원 수준을 선택하고 이전 시스템의 스칼라 구현으로 돌아가는 것을 제안합니다.

이것은 또한 장치/회귀 테스트에 이상적인 상황이며, 이는 다른 구현이 동일한 결과를 생성하는 데 매우 중요합니다. 입력 데이터의 테스트 스위트와 알려진 우수한 출력 데이터를 가지고 있으며 처리 기능의 두 버전을 통해 동일한 데이터를 실행하십시오. 통과에 대한 정밀 테스트가 필요할 수 있습니다 (예 : 결과와 정답 사이의 엡실론은 다음과 같습니다. 1e6, 예를 들어). 이렇게하면 디버깅에 크게 도움이되며 테스트 프레임 워크에 고해상도 타이밍을 구축하면 성능 향상을 동시에 비교할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top