我想我应该熟悉x86 SIMD扩展.但在我开始之前,我遇到了麻烦.我无法找到关于哪些仍然相关的良好概述.
几十年来,x86架构积累了大量的数学/多媒体扩展:
较新的超集是旧的超集,反之亦然?或者它们是互补的吗?
有些人已被弃用吗?哪些仍然相关?我听说过"遗留SSE".
有些是互斥的吗?即他们共享相同的硬件部分?
我应该一起使用哪个来最大化现代Intel/AMD CPU的硬件利用率?为了争论,让我们假设我可以找到适当的指令用途...如果没有别的话,用CPU加热我的房子.
我在哪里可以找到有关常见SIMD技巧的信息?我有一个指令集,知道如何编写非棘手的SIMD代码,但我知道,SIMD现在功能更强大.它可以保存复杂的条件无分支代码.
例如(ARMv6),以下指令序列将Rd的每个字节设置为等于Ra和Rb的相应字节的无符号最小值:
USUB8 Rd, Ra, Rb
SEL Rd, Rb, Ra
Run Code Online (Sandbox Code Playgroud)
教程/非常见SIMD技术的链接也很好:) ARMv6对我来说是最有趣的,但x86(SSE,...)/ Neon(在ARMv7中)/其他也很好.
我试图通过使用内联汇编的MMX和SSE指令集来优化某些算法.但是,我无法找到这些增强指令集的时序和用法的良好参考.你能否帮我找一些参考文献,其中包含有关吞吐量,延迟,操作数以及说明的简短描述的信息?
到目前为止,我发现:
英特尔指令参考 英特尔64和IA-32架构开发人员手册:Vol.2A和 Intel 64和IA-32架构开发人员手册:Vol.2B
我目前正在学习英特尔x86处理器上的汇编编程.
有人可以向我解释一下,MMX和XMM注册有什么区别?我对他们所服务的功能以及它们之间的差异和相似性感到非常困惑?
因此,当我开始转换并将目标设置为'x64'时,我得到7个未解析的外部.两个例子:
error LNK2001: unresolved external symbol _m_empty ...CONVOLUTION_2D_USHORT.obj CONVOLUTION_2D_USHORT
error LNK2001: unresolved external symbol _mm_setzero_si64 ...CONVOLUTION_2D_USHORT.obj CONVOLUTION_2D_USHORT
Run Code Online (Sandbox Code Playgroud)
所以我试着更深入地研究这些,我发现它不喜欢头文件中的__m64:特别是mmintrin.h(可能还有其他的).在我使用C++的业余时间,因为我多年来没有弄乱语言,(我通常在C#部门),我试图编辑头文件,并用__m128i替换__m64 !! !! 不知道什么是正确的路由,让这个和其他DLL编译对MachineX64.编辑并将标题源放在我的本地目录后,它仍然不允许我通过右键单击...再次 - 业余小时编译.有几个人问过类似的问题,但我找不到合适的问题.
以下是'mmintrin.h'的示例,其中包含不受支持的__m64 ...
typedef union __declspec(intrin_type)_CRT_ALIGN(8) __m64
{
unsigned __int64 m64_u64;
float m64_f32[2];
__int8 m64_i8[8];
__int16 m64_i16[4];
__int32 m64_i32[2];
__int64 m64_i64;
unsigned __int8 m64_u8[8];
unsigned __int16 m64_u16[4];
unsigned __int32 m64_u32[2];
} __m64;
/* General support intrinsics */
void _m_empty(void);
__m64 _m_from_int(int _I);
int _m_to_int(__m64 _M);
__m64 _m_packsswb(__m64 _MM1, __m64 _MM2);
__m64 _m_packssdw(__m64 _MM1, __m64 _MM2);
__m64 _m_packuswb(__m64 _MM1, …Run Code Online (Sandbox Code Playgroud) 我在NASM中编写了这段代码:
PADDD mm0, mm1
Run Code Online (Sandbox Code Playgroud)
并且没有任何错误组装,但是这条指令虽然存在于NASM中,但我在"英特尔说明手册"中找不到它,我发现的全是:
PADDD xmm1, xmm2/m128
Run Code Online (Sandbox Code Playgroud)
这需要xmm注册而不是mm注册.
这是操作码PADDD mm0, mm1:0FFEC1
这是操作码PADDD xmm0, xmm1:660FFEC1
那么为什么PADDD mm0, mm1缺少英特尔指令手册?
我正在尝试重振使用3DNow的旧Win32游戏!指令集进行3D渲染.
在像Win7这样的现代操作系统上 - 不允许像FPADD或FPMUL这样的Win10指令,程序会抛出异常.
自从3DNow的数量!游戏使用的指令非常有限,在我的VS2008 MFC程序中,我试图使用向量异常处理来获取MMX寄存器的值,模拟3DNow!C代码指令并将值推回处理器3DNow!寄存器.
到目前为止,我成功完成了前两个步骤(我从ExceptionInfo->ExtendedRegisters偏移量为32的字节数组中获取mmx寄存器值并使用浮点类型C指令进行计算),但我的问题是,无论我如何尝试更新MMX寄存器值的寄存器价值似乎保持不变.
假设我的_asm陈述可能是错误的,我还使用这样的简单语句进行了一些最小的测试:
_asm movq mm0 mm7
Run Code Online (Sandbox Code Playgroud)
执行此语句没有其他例外,但在检索MMX寄存器值时,我仍然发现原始值未更改.
如何使作业有效?
我很好奇,新的编译器使用内置在新CPU中的一些额外功能,如MMX SSE,3DNow!所以?
我的意思是,在最初的8086中甚至没有FPU,所以旧的编译器甚至不能使用它,但是新的编译器可以,因为FPU是每个新CPU的一部分.那么,新的编译器是否使用了CPU的新功能?
或者,更新的问题是,新的C/C++标准库函数是否使用新功能?
谢谢你的回答.
编辑:
好的,所以,如果我能帮到你们所有人,即使是一些标准操作,特别是浮点数也可以使用SSE更快地完成.
为了使用它,我必须在我的编译器中启用此功能,如果它支持它.如果是这样,我必须确保目标平台支持该功能.
如果某些系统库需要最高性能,例如OpenGL,DirectX等,系统可能支持此支持.
默认情况下,出于兼容性原因,编译器不支持它,但您可以使用由Intel提供的特殊C函数来添加此支持.这应该是最好的方法,因为您可以直接控制天气以及何时使用所需平台的特殊功能来编写支持多CPU的应用程序.
将__int64值转换__m64为与SSE一起使用的值的正确方法是什么?
我正在尝试使用SSE内在函数优化一小段代码(我是关于该主题的完全初学者),但我有点坚持使用条件.
我原来的代码是:
unsigned long c;
unsigned long constant = 0x12345678;
unsigned long table[256];
int n, k;
for( n = 0; n < 256; n++ )
{
c = n;
for( k = 0; k < 8; k++ )
{
if( c & 1 ) c = constant ^ (c >> 1);
else c >>= 1;
}
table[n] = c;
}
Run Code Online (Sandbox Code Playgroud)
这段代码的目标是计算一个crc表(常量可以是任何多项式,它在这里不起作用),
我想我的优化代码是这样的:
__m128 x;
__m128 y;
__m128 *table;
x = _mm_set_ps(3, 2, 1, 0);
y = _mm_set_ps(3, 2, 1, 0); …Run Code Online (Sandbox Code Playgroud)