我在Solaris 11上使用Sun Studio 12.4和12.5.我们有一个源文件,它提供CRC32的直接C / C ++实现,或使用Intel内在函数的CRC32的优化版本。在运行时,使用正确的实现填充函数指针。
在具有双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确实不定义习惯性GCC定义,例如__SSE4_1__
和__SSE4_2__
。此外,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
答案 0 :(得分:3)
关于你的第二个问题:
如何禁用-xarch位,以便程序可以在低级处理器上运行?
参见第7章链接器和库指南的能力处理:
https://docs.oracle.com/cd/E53394_01/html/E54813/index.html
这将向您展示如何提供相同功能的多个实例 用能力位标记。运行时链接器将 根据报告的功能解决使用哪个功能。
如果您真的想自己管理功能位, 请参阅第9章Mapfiles特定部分CAPABILITY Directive。 这显示了如何从生成的对象中删除功能。
答案 1 :(得分:2)
我相信,对于你的特殊情况(它的第二部分),你想要的唯一简单方法就是这样:用明确设置编译" -xarch = sse4.2" (这允许编译器扩展SSE4.2内部函数),然后将HWCAP位剥离到最小的体系结构(这使得您的程序可以在SSE4.2之前的硬件上运行)。
剥离HWCAP请参阅: https://docs.oracle.com/cd/E23823_01/html/816-5165/elfedit-1.html
(示例2:删除硬件功能位)
答案 2 :(得分:1)
首先,您不希望从已编译的二进制文件中删除指令集标志。使用-xarch=NNNN
选项进行编译时,编译将使用这些指令。如果你试图在"较低的"处理器没有实现您在-xarch
参数中提供的体系结构的指令,您的二进制文件很有可能无法正常工作。
来自Solaris Studio 12.4: C User's Guide:
1.3二进制兼容性验证
在Solaris系统上,从Solaris Studio 11开始,编写二进制文件 使用Oracle Solaris Studio编译器编译的标记为 架构硬件标志,指示所采用的指令集 编译的二进制文件在运行时,将检查这些标记标记 验证二进制文件是否可以在它尝试的硬件上运行 执行。
运行不包含这些体系结构硬件标志的程序 在未启用相应功能的平台上 指令集扩展可能导致分段错误或 在没有任何明确警告消息的情况下发生错误结果。
还要注意功能和指令集的提及。根据我对Solaris文档的经验,一点一点就足以警告可能还有很多东西
我不知道通过预处理器检测可用指令集的任何方法。您可以在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 Studio的Oracle论坛的帮助我怀疑即使在那里,你也找不到使用预处理器的方法。在Solaris上提供平台和指令集特定实现的常用方法是通过特定的共享对象。来自Solaris Linker and Libraries Guide:
指令集特定共享对象
动态令牌
$ISALIST
在运行时展开以反映 本平台上可执行的本机指令集,如下所示 实用程序isalist(1)
。包含
$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
请注意库搜索是如何从"最高"开始的。指令集特定的库,并移动到"降低"库。这允许定位多个指令集特定的共享对象,来自"最快的特定"到#34;最慢的通用"。 Solaris上的libc.so
执行此操作以提供特定于平台的库函数版本,例如memcpy()
。