- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
当我可以使用 SSE3 或 AVX 时,SSE2 或 MMX 等较旧的 SSE 版本是否可用 -
还是我还需要单独检查它们?
最佳答案
一般来说,这些都是附加的,但请记住,多年来英特尔和 AMD 对这些的支持有所不同。
如果您有 AVX,那么您也可以使用 SSE、SSE2、SSE3、SSSE3、SSE4.1 和 SSE 4.2。请记住,要使用 AVX,您还需要验证 OSXSAVE CPUID 位是否已设置,以确保您使用的操作系统实际上也支持保存 AVX 寄存器。
您仍应明确检查您在代码中使用的所有 CPUID 支持以确保稳健性(比如同时检查 AVX、OSXSAVE、SSE4、SSE3、SSSE3 以保护您的 AVX 代码路径)。
#include <intrin.h>
inline bool IsAVXSupported()
{
#if defined(_M_IX86 ) || defined(_M_X64)
int CPUInfo[4] = {-1};
__cpuid( CPUInfo, 0 );
if ( CPUInfo[0] < 1 )
return false;
__cpuid(CPUInfo, 1 );
int ecx = 0x10000000 // AVX
| 0x8000000 // OSXSAVE
| 0x100000 // SSE 4.2
| 0x80000 // SSE 4.1
| 0x200 // SSSE3
| 0x1; // SSE3
if ( ( CPUInfo[2] & ecx ) != ecx )
return false;
return true;
#else
return false;
#endif
}
所有支持 x64 native 的处理器都需要 SSE 和 SSE2,因此它们是所有代码的良好基准假设。 Windows 8.0、Windows 8.1 和 Windows 10 明确要求 SSE 和 SSE2 支持,即使对于 x86 架构也是如此,因此这些指令集非常普遍。换句话说,如果您未能通过 SSE 或 SSE2 检查,只需退出应用程序并出现 fatal error 。
#include <windows.h>
inline bool IsSSESupported()
{
#if defined(_M_IX86 ) || defined(_M_X64)
return ( IsProcessorFeaturePresent( PF_XMMI_INSTRUCTIONS_AVAILABLE ) != 0 && IsProcessorFeaturePresent( PF_XMMI64_INSTRUCTIONS_AVAILABLE ) != 0 );
#else
return false;
#endif
}
-或-
#include <intrin.h>
inline bool IsSSESupported()
{
#if defined(_M_IX86 ) || defined(_M_X64)
int CPUInfo[4] = {-1};
__cpuid( CPUInfo, 0 );
if ( CPUInfo[0] < 1 )
return false;
__cpuid(CPUInfo, 1 );
int edx = 0x4000000 // SSE2
| 0x2000000; // SSE
if ( ( CPUInfo[3] & edx ) != edx )
return false;
return true;
#else
return false;
#endif
}
此外,请记住 MMX、x87 FPU 和 AMD 3DNow! * 都是针对 x64 native 的已弃用指令集,因此您不应再在较新的代码中主动使用它们。一个好的经验法则是避免使用任何返回 __m64
或采用 __m64
数据类型的内部函数。
您可能想看看这个 DirectXMath blog series附有许多这些指令集和相关处理器支持要求的注释。
注意 (*) - 所有 AMD 3DNow!除了 PREFETCH
和 PREFETCHW
外,指令已弃用。第一代 Intel64 处理器不支持这些指令,但后来添加了它们,因为它们被认为是核心 X64 指令集的一部分。 Windows 8.1 和 Windows 10 x64 特别需要 PREFETCHW
,尽管测试有点奇怪。 Broadwell 之前的大多数英特尔 CPU 实际上并未通过 CPUID 报告对 PREFETCHW
的支持,但它们将操作码视为空操作,而不是抛出“非法指令”异常。因此,这里的测试是 (a) CPUID 是否支持它,以及 (b) 如果不支持,PREFETCHW
是否至少不抛出异常。
下面是 Visual Studio 的一些测试代码,演示了 PREFETCHW
测试以及 x86 和 x64 平台的许多其他 CPUID 位。
#include <intrin.h>
#include <stdio.h>
#include <windows.h>
#include <excpt.h>
void main()
{
unsigned int x = _mm_getcsr();
printf("%08X\n", x );
bool prefetchw = false;
// See http://msdn.microsoft.com/en-us/library/hskdteyh.aspx
int CPUInfo[4] = {-1};
__cpuid( CPUInfo, 0 );
if ( CPUInfo[0] > 0 )
{
__cpuid(CPUInfo, 1 );
// EAX
{
int stepping = (CPUInfo[0] & 0xf);
int basemodel = (CPUInfo[0] >> 4) & 0xf;
int basefamily = (CPUInfo[0] >> 8) & 0xf;
int xmodel = (CPUInfo[0] >> 16) & 0xf;
int xfamily = (CPUInfo[0] >> 20) & 0xff;
int family = basefamily + xfamily;
int model = (xmodel << 4) | basemodel;
printf("Family %02X, Model %02X, Stepping %u\n", family, model, stepping );
}
// ECX
if ( CPUInfo[2] & 0x20000000 ) // bit 29
printf("F16C\n");
if ( CPUInfo[2] & 0x10000000 ) // bit 28
printf("AVX\n");
if ( CPUInfo[2] & 0x8000000 ) // bit 27
printf("OSXSAVE\n");
if ( CPUInfo[2] & 0x400000 ) // bit 22
printf("MOVBE\n");
if ( CPUInfo[2] & 0x100000 ) // bit 20
printf("SSE4.2\n");
if ( CPUInfo[2] & 0x80000 ) // bit 19
printf("SSE4.1\n");
if ( CPUInfo[2] & 0x2000 ) // bit 13
printf("CMPXCHANG16B\n");
if ( CPUInfo[2] & 0x1000 ) // bit 12
printf("FMA3\n");
if ( CPUInfo[2] & 0x200 ) // bit 9
printf("SSSE3\n");
if ( CPUInfo[2] & 0x1 ) // bit 0
printf("SSE3\n");
// EDX
if ( CPUInfo[3] & 0x4000000 ) // bit 26
printf("SSE2\n");
if ( CPUInfo[3] & 0x2000000 ) // bit 25
printf("SSE\n");
if ( CPUInfo[3] & 0x800000 ) // bit 23
printf("MMX\n");
}
else
printf("CPU doesn't support Feature Identifiers\n");
if ( CPUInfo[0] >= 7 )
{
__cpuidex(CPUInfo, 7, 0);
// EBX
if ( CPUInfo[1] & 0x100 ) // bit 8
printf("BMI2\n");
if ( CPUInfo[1] & 0x20 ) // bit 5
printf("AVX2\n");
if ( CPUInfo[1] & 0x8 ) // bit 3
printf("BMI\n");
}
else
printf("CPU doesn't support Structured Extended Feature Flags\n");
// Extended features
__cpuid( CPUInfo, 0x80000000 );
if ( CPUInfo[0] > 0x80000000 )
{
__cpuid(CPUInfo, 0x80000001 );
// ECX
if ( CPUInfo[2] & 0x10000 ) // bit 16
printf("FMA4\n");
if ( CPUInfo[2] & 0x800 ) // bit 11
printf("XOP\n");
if ( CPUInfo[2] & 0x100 ) // bit 8
{
printf("PREFETCHW\n");
prefetchw = true;
}
if ( CPUInfo[2] & 0x80 ) // bit 7
printf("Misalign SSE\n");
if ( CPUInfo[2] & 0x40 ) // bit 6
printf("SSE4A\n");
if ( CPUInfo[2] & 0x1 ) // bit 0
printf("LAHF/SAHF\n");
// EDX
if ( CPUInfo[3] & 0x80000000 ) // bit 31
printf("3DNow!\n");
if ( CPUInfo[3] & 0x40000000 ) // bit 30
printf("3DNowExt!\n");
if ( CPUInfo[3] & 0x20000000 ) // bit 29
printf("x64\n");
if ( CPUInfo[3] & 0x100000 ) // bit 20
printf("NX\n");
}
else
printf("CPU doesn't support Extended Feature Identifiers\n");
if ( !prefetchw )
{
bool illegal = false;
__try
{
static const unsigned int s_data = 0xabcd0123;
_m_prefetchw(&s_data);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
illegal = true;
}
if (illegal)
{
printf("PREFETCHW is an invalid instruction on this processor\n");
}
}
}
更新:当然,最根本的挑战是如何处理不支持 AVX 的系统?虽然指令集很有用,但拥有支持 AVX 的处理器的最大好处是能够使用 /arch:AVX
构建开关,它可以在全局范围内使用 VEX prefix。以获得更好的 SSE/SSE2 代码生成。唯一的问题是生成的代码 DLL/EXE 与缺乏 AVX 支持的系统不兼容。
因此,对于 Windows,理想情况下您应该为非 AVX 系统构建一个 EXE(假设仅使用 SSE/SSE2,因此对 x86 代码使用 /arch:SSE2
;此设置对于 x64 是隐式的代码),一个针对 AVX 优化的不同 EXE(使用 /arch:AVX
),然后使用 CPU 检测来确定给定系统使用哪个 EXE。
幸运的是,有了 Xbox One,我们总是可以使用 /arch::AVX
进行构建,因为它是一个固定平台...
更新 2:对于 clang/LLVM,您应该为 CPUID
使用轻微的 dikyfferent intriniscs:
if defined(__clang__) || defined(__GNUC__)
__cpuid(1, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
#else
__cpuid(CPUInfo, 1);
#endif
if defined(__clang__) || defined(__GNUC__)
__cpuid_count(7, 0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
#else
__cpuidex(CPUInfo, 7, 0);
#endif
关于c++ - 使用较新的 SIMD 版本时是否可以使用较旧的 SIMD 版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30355620/
我有一个 if 语句,如下所示 if (not(fullpath.lower().endswith(".pdf")) or not (fullpath.lower().endswith(tup
然而,在 PHP 中,可以: only appears if $foo is true. only appears if $foo is false. 在 Javascript 中,能否在一个脚
XML有很多好处。它既是机器可读的,也是人类可读的,它具有标准化的格式,并且用途广泛。 它也有一些缺点。它是冗长的,不是传输大量数据的非常有效的方法。 XML最有用的方面之一是模式语言。使用模式,您可
由于长期使用 SQL2000,我并没有真正深入了解公用表表达式。 我给出的答案here (#4025380)和 here (#4018793)违背了潮流,因为他们没有使用 CTE。 我很欣赏它们对于递
我有一个应用程序: void deleteObj(id){ MyObj obj = getObjById(id); if (obj == null) { throw n
我的代码如下。可能我以类似的方式多次使用它,即简单地说,我正在以这种方式管理 session 和事务: List users= null; try{ sess
在开发J2EE Web应用程序时,我通常会按以下方式组织我的包结构 com.jameselsey.. 控制器-控制器/操作转到此处 服务-事务服务类,由控制器调用 域-应用程序使用的我的域类/对象 D
这更多是出于好奇而不是任何重要问题,但我只是想知道 memmove 中的以下片段文档: Copying takes place as if an intermediate buffer were us
路径压缩涉及将根指定为路径上每个节点的新父节点——这可能会降低根的等级,并可能降低路径上所有节点的等级。有办法解决这个问题吗?有必要处理这个吗?或者,也许可以将等级视为树高的上限而不是确切的高度? 谢
我有两个类,A 和 B。A 是 B 的父类,我有一个函数接收指向 A 类型类的指针,检查它是否也是 B 类型,如果是将调用另一个函数,该函数接受一个指向类型 B 的类的指针。当函数调用另一个函数时,我
有没有办法让 valgrind 使用多个处理器? 我正在使用 valgrind 的 callgrind 进行一些瓶颈分析,并注意到我的应用程序中的资源使用行为与在 valgrind/callgrind
假设我们要使用 ReaderT [(a,b)]超过 Maybe monad,然后我们想在列表中进行查找。 现在,一个简单且不常见的方法是: 第一种可能性 find a = ReaderT (looku
我的代码似乎有问题。我需要说的是: if ( $('html').attr('lang').val() == 'fr-FR' ) { // do this } else { // do
根据this文章(2018 年 4 月)AKS 在可用性集中运行时能够跨故障域智能放置 Pod,但尚不考虑更新域。很快就会使用更新域将 Pod 放入 AKS 中吗? 最佳答案 当您设置集群时,它已经自
course | section | type comart2 : bsit201 : lec comart2 :
我正在开发自己的 SDK,而这又依赖于某些第 3 方 SDK。例如 - OkHttp。 我应该将 OkHttp 添加到我的 build.gradle 中,还是让我的 SDK 用户包含它?在这种情况下,
随着 Rust 越来越充实,我对它的兴趣开始激起。我喜欢它支持代数数据类型,尤其是那些匹配的事实,但是对其他功能习语有什么想法吗? 例如标准库中是否有标准过滤器/映射/归约函数的集合,更重要的是,您能
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
我一直在研究 PHP 中的对象。我见过的所有示例甚至在它们自己的对象上都使用了对象构造函数。 PHP 会强制您这样做吗?如果是,为什么? 例如: firstname = $firstname;
...比关联数组? 关联数组会占用更多内存吗? $arr = array(1, 1, 1); $arr[10] = 1; $arr[] = 1; // <- index is 11; does the
我是一名优秀的程序员,十分优秀!