2016-07-12 7 views
2

Solaris 11에서 Sun Studio 12.4 및 12.5를 사용하고 있습니다. 인텔 고유의 내장 함수를 사용하여 CRC32의 C/C++ 구현 또는 CRC32의 최적화 된 버전을 제공하는 소스 파일이 있습니다. 런타임에는 함수 포인터가 적절한 구현으로 채워집니다.전 처리기에서 -xarch 옵션을 감지합니까?

이중 Xeon을 사용하는 x86 서버에서 테스트하는 것은 컴파일러 버전에 따라 코드 경로를 사용할 수 있도록하기 때문에 다음을 생성합니다. SunCC 12.1은 SSE4에 대한 지원을 추가 했으므로 (올바르게 매트릭스를 파싱 한 경우) __SUNPRO_CC >= 0x5100으로 설정할 수 있습니다.

"crc.cpp", line 311: ube: error: _mm_crc32_u8 intrinsic requires at least -xarch=sse4_2. 

SunCC는 하지__SSE4_1____SSE4_2__ 같은 관습 GCC의 정의를 정의한다. 또한 SunCC는 컴파일러 버전에서 지원을 나타내는 MS VC++와 같은 내장 함수를 사용할 수있는 것으로 보이지 않습니다.

SunCC가 -xarch 옵션을 기반으로 기능을 활성화하는 것처럼 보입니다. 그러나 선 처리기에서이를 감지하는 방법이 명확하지 않습니다. 또한 -xarch을 사용하면 하위 프로세서 ("최소"플랫폼과 같은 것)에서 프로그램이 실패하는 일부 비트가 설정됩니다.

두 가지 질문이 있습니다.

  • 전 처리기에서 -xarch 옵션을 어떻게 감지합니까?
  • -xarch 비트를 어떻게 비활성화하여 프로그램이 하위 수준 프로세서에서 실행될 수 있습니까? 다음은

-xarch=aes로 컴파일 매크로 덤프에서입니다. 사용할 수있는 기능을 나타내는 것은 없습니다.

$ /opt/solarisstudio12.4/bin/CC -native -m64 -xarch=aes -xdumpmacros -E /dev/null 2>&1 | /usr/gnu/bin/sort --ignore-case 

#1 "/dev/null" 
#define __alignof__ __alignof 
#define __amd64 1 
#define __amd64__ 1 
#define __ARRAYNEW 1 
#define __asm asm 
#define __asm__ asm 
#define __attribute __attribute__ 
#define __builtin_constant_p __oracle_builtin_constant_p 
#define __builtin_fpclassify __oracle_builtin_fpclassify 
#define __builtin_huge_val __oracle_builtin_huge_val 
#define __builtin_huge_valf __oracle_builtin_huge_valf 
#define __builtin_huge_vall __oracle_builtin_huge_vall 
#define __builtin_infinity __oracle_builtin_infinity 
#define __builtin_isfinite __oracle_builtin_isfinite 
#define __builtin_isgreater __oracle_builtin_isgreater 
#define __builtin_isgreaterequal __oracle_builtin_isgreaterequal 
#define __builtin_isinf __oracle_builtin_isinf 
#define __builtin_isless __oracle_builtin_isless 
#define __builtin_islessequal __oracle_builtin_islessequal 
#define __builtin_islessgreater __oracle_builtin_islessgreater 
#define __builtin_isnan __oracle_builtin_isnan 
#define __builtin_isnormal __oracle_builtin_isnormal 
#define __builtin_isunordered __oracle_builtin_isunordered 
#define __builtin_nan __oracle_builtin_nan 
#define __builtin_signbit __oracle_builtin_signbit 
#define __BUILTIN_VA_STRUCT 1 
#define __cplusplus 199711L 
#define __DATE__ "Jul 11 2016" 
#define __FILE__ 
#define __has_attribute(x) __oracle_has_attribute(x) 
#define __has_nothrow_assign(x) __oracle_has_nothrow_assign(x) 
#define __has_nothrow_constructor(x) __oracle_has_nothrow_constructor(x) 
#define __has_nothrow_copy(x) __oracle_has_nothrow_copy(x) 
#define __has_trivial_assign(x) __oracle_has_trivial_assign(x) 
#define __has_trivial_constructor(x) __oracle_has_trivial_constructor(x) 
#define __has_trivial_copy(x) __oracle_has_trivial_copy(x) 
#define __has_trivial_destructor(x) __oracle_has_trivial_destructor(x) 
#define __has_virtual_destructor(x) __oracle_has_virtual_destructor(x) 
#define __is_abstract(x) __oracle_is_abstract(x) 
#define __is_base_of(x,y) __oracle_is_base_of(x,y) 
#define __is_class(x) __oracle_is_class(x) 
#define __is_empty(x) __oracle_is_empty(x) 
#define __is_enum(x) __oracle_is_enum(x) 
#define __is_final(x) __oracle_is_final(x) 
#define __is_literal_type(x) __oracle_is_literal_type(x) 
#define __is_pod(x) __oracle_is_pod(x) 
#define __is_polymorphic(x) __oracle_is_polymorphic(x) 
#define __is_standard_layout(x) __oracle_is_standard_layout(x) 
#define __is_trivial(x) __oracle_is_trivial(x) 
#define __is_union(x) __oracle_is_union(x) 
#define __LINE__ 
#define __LP64__ 1 
#define __PRAGMA_REDEFINE_EXTNAME 1 
#define __STDC__ 0 
#define __sun 1 
#define __SUN_PREFETCH 1 
#define __SunOS 1 
#define __SunOS_5_11 1 
#define __SUNPRO_CC 0x5130 
#define __SUNPRO_CC_COMPAT 5 
#define __SVR4 1 
#define __TIME__ "20:58:00" 
#define __underlying_type(x) __oracle_underlying_type(x) 
#define __unix 1 
#define __volatile volatile 
#define __volatile__ volatile 
#define __x86_64 1 
#define __x86_64__ 1 
#define _BOOL 1 
#define _LARGEFILE64_SOURCE 1 
#define _LP64 1 
#define _SIGNEDCHAR_ 1 
#define _TEMPLATE_NO_EXTDEF 1 
#define _WCHAR_T 
#define sun 1 
#define unix 1 

답변

3

? 링커 및 라이브러리 설명서의

제 7 장 기능의 처리 :

https://docs.oracle.com/cd/E53394_01/html/E54813/index.html

이 어떻게 기능 비트와 태그 같은 기능 의 여러 인스턴스를 제공하는 방법을 보여줍니다. 런타임 링커는보고 된 기능을 기반으로 어떤 기능이 사용되는지를 해결합니다.

실제로 능력 비트를 직접 관리하려면 9 장 맵 파일, 특히 CAPABILITY 지시문을 참조하십시오. 생성 된 개체에서 기능을 제거하는 방법을 보여줍니다.

+0

감사 존 : HWCAP 볼 제거에 대한

. 우리는 런타임시 코드 경로를 보호하므로 일반적으로 컴파일러 만 있으면 ASM 또는 내장 함수를 사용할 수 있습니다. 즉, SSE2를 빌드하고 최적화 된 SSE3 및 SSE4 구현과 같이 나머지는 처리 할 수 ​​있습니다. 예를 들어 [crc.cpp] (http://github.com/weidai11/cryptopp/blob/master/crc.cpp) 및 [blake2.cpp] (http://github.com/weidai11/cryptopp/)를 참조하십시오. blob/master/blake2.cpp). – jww

+0

당신이 참조하는 가드가 HasSSE2()와 HasSSE4() 같은 함수라고 가정합니다. 이러한 런타임에서 하드웨어 기능을 확인하면 Studio에서 -Mmapfile 옵션을 추가하여 컴파일하면됩니다. mapfile은 "HW - = SSE2"와 같은 CAPABILITY 항목을 포함합니다. 대체 기능을 제공하는 가장 낮은 성능의 시스템에서 실행해야하는 각 기능을 마스크하십시오. –

+0

감사합니다. 솔라리스에 관해 배워야 할 부분이 너무 많습니다. 수년간, 그것은 C/C++ 구현만을 가지고있는 빨간 머리 단계 자식이었습니다. 학습 활동으로, 나는 그것을 일류 시민으로 만들고 싶었고 모든 속도 향상을 얻었습니다. (GCC 인라인 어셈블리를 처음 사용하는 Sun Studio 12.1 이상). – jww

1

먼저 컴파일 된 바이너리에서 명령어 세트 플래그를 제거하지 않으려합니다. -xarch=NNNN 옵션을 사용하여 컴파일하면 해당 지침이 사용됩니다. -xarch 인수에서 제공 한 아키텍처의 지침을 구현하지 않는 "낮은"프로세서에서 실행하려고하면 이진 파일이 제대로 작동하지 않을 수 있습니다. Solaris Studio 12.4: C User's Guide에서

:

1.3 이진 호환성 검증 Solaris 시스템

, 스튜디오 11 솔라리스로 시작은, 오라클 솔라리스 스튜디오 컴파일러로 컴파일 된 프로그램 바이너리 는 아키텍처 하드웨어가 표시되어 있습니다 컴파일 된 바이너리 인 에 의해 가정 된 명령 세트를 나타내는 플래그. 실행시이 마커 플래그는 으로 확인되어 이진 코드가 실행을 시도하는 하드웨어에서 실행될 수 있는지 확인합니다. 세그멘테이션 오류 또는 명시 적으로 경고 메시지없이 발생 잘못된 결과가 발생할 수 있습니다 적절한 기능이나 명령어 세트 확장을 사용할 수 없습니다 플랫폼에서 이러한 아키텍처 하드웨어 플래그를 포함하지 않는 프로그램을 실행

.

또한 명령 세트와 기능에 대한 언급에 유의하십시오. 솔라리스 문서를 가지고 경험 한 바에 따르면 조금은 따로두고도 충분하다는 경고가 충분합니다.

전처리기를 통해 사용 가능한 명령어 세트를 감지하는 방법을 모른다. https://community.oracle.com/community/server_%26_storage_systems/application_development_in_c__c%2B%2B__and_fortran/developer_studio_c_c%2B%2B_fortran_compilers

나는 심지어 거기에서 전처리기를 사용할 방법을 찾지 못할 것이라고 생각합니다. Solaris에서 플랫폼 및 명령 세트 특정 구현을 제공하는 일반적인 방법은 특정 공유 객체를 사용하는 것입니다. Solaris Linker and Libraries Guide에서 : 특정 공유 설정

명령 유틸리티 isalist(1)에 의해 표시되는

동적 토큰 $ISALIST가 기본 지침을 반영하기 위해 런타임시에 확장이이 플랫폼에서 실행 설정 개체.

$ISALIST 토큰이 포함 된 문자열 이름은 실제로 이 여러 문자열로 복제됩니다. 각 문자열에는 사용 가능한 명령어 세트 중 하나가 할당됩니다. 이 토큰은 필터 또는 runpath 사양에만 사용할 수 있습니다.

...

또는 유사한 종속성이있는 응용 프로그램

MMX Pentium Pro 구성에서 실행되는 : 라이브러리 검색이 "최고"명령 세트 특정 라이브러리로 시작하는 방법

$ ldd -ls prog 
..... 
    find object=libbar.so.1; required by ./libfoo.so.1 
    search path=/opt/ISV/lib/$ISALIST (RPATH from file ./libfoo.so.1) 
     trying path=/opt/ISV/lib/pentium_pro+mmx/libbar.so.1 
     trying path=/opt/ISV/lib/pentium_pro/libbar.so.1 
     trying path=/opt/ISV/lib/pentium+mmx/libbar.so.1 
     trying path=/opt/ISV/lib/pentium/libbar.so.1 
     trying path=/opt/ISV/lib/i486/libbar.so.1 
     trying path=/opt/ISV/lib/i386/libbar.so.1 
     trying path=/opt/ISV/lib/i86/libbar.so.1 

주 , "하위"라이브러리로 이동합니다. 이를 통해 "가장 빠른 특정"에서 "가장 느린 일반"에 이르기까지 여러 명령 세트 특정 공유 객체를 찾을 수 있습니다. Solaris의 libc.somemcpy()과 같은 라이브러리 기능의 플랫폼 특정 버전을 제공하기 위해이 작업을 수행합니다. 프로그램이 아래 수준의 프로세서에서 실행할 수 있도록 내가 -xarch 비트를 사용하지 않는 방법

: 두 번째 질문에 대한

2

필자는 특정 상황 (두 번째 부분)에서 원하는 것을 수행하는 유일한 방법은 다음과 같다고 생각합니다. 명시 적으로 "-xarch = sse4.2"로 컴파일하면 컴파일러에서 SSE4를 확장 할 수 있습니다 .2 intrinsics). 그런 다음 HWCAP 비트를 최소 아키텍처로 제거합니다 (이렇게하면 SSE4.2 이전 하드웨어에서 프로그램을 실행할 수 있습니다). https://docs.oracle.com/cd/E23823_01/html/816-5165/elfedit-1.html

(예 2 하드웨어 기능 비트 제거)

+0

'-xarch = sse4.2'로 컴파일하면 컴파일러가 SSE4.2 내장 함수를 사용할 수 있습니다. 나중에 SSE4.2 HWCAP 비트를 제거하면 해당 내장 함수를 사용하는 바이너리가 생성 될 수 있으므로 비 SSE4.2 가능 하드웨어에서 실행되지 않습니다. 64 비트 바이너리를 컴파일하지 않고 32 비트 바이너리로 읽도록 ELF 헤더를 수정하고 32 비트 하드웨어에서 실행되도록 기대 하시겠습니까? –

+0

topic-startter는 앱이 실행되는 하드웨어에 따라 적절한 구현을 선택하기 위해 런타임에 경비원을두고 있다고 언급했습니다. 나는 일반적인 경우에 HWCAP이 무엇인지 알고 있습니다. 하지만이 사건은 특별합니다. 컴파일러가 코드의 비 내장 부분에 대해 비 SSE2를 방출하는 경우가있을 수 있습니다. 이를 점검해야합니다. P. ELF32와 ELF64는 HWCAP 섹션의 일부 값이 아닌 ELF 자체의 속성입니다. 그래서, 당신은 여기에서 너무 긴장하고 있습니다. – Anton

+0

* topic-startter는 응용 프로그램이 실행되는 하드웨어에 따라 적절한 구현을 선택하기 위해 런타임 가드가 있다고 언급했습니다. * 제공되는 런타임 가드 예제는 제공되는 컴파일 된 코드를 보호한다는 것이 확실하지 않습니다. SSE2와 같은 특정 명령 세트 제공된 예제에서 가드 외부의 코드 *도 이러한 명령어 세트를 사용하는 옵션으로 컴파일되므로 HWCAP 비트를 제거하면 특정 기능을 구현하지 않는 하드웨어가 여전히 필요한 명령어로 실행될 수 있습니다. –

관련 문제