我的C++代码使用SSE,现在我想改进它以支持AVX可用时.所以我检测AVX何时可用并调用使用AVX命令的函数.我使用Win7 SP1 + VS2010 SP1和带AVX的CPU.
要使用AVX,必须包含以下内容:
#include "immintrin.h"
Run Code Online (Sandbox Code Playgroud)
然后你可以使用内在的AVX函数_mm256_mul_ps,_mm256_add_ps等等.问题是,默认情况下,VS2010产生的代码工作得非常慢,并显示警告:
警告C4752:发现英特尔(R)高级矢量扩展; 考虑使用/ arch:AVX
似乎VS2010实际上不使用AVX指令,而是模仿它们.我添加/arch:AVX到编译器选项并获得了良好的结果.但是这个选项告诉编译器尽可能在任何地方使用AVX命令.所以我的代码可能会崩溃在不支持AVX的CPU上!
所以问题是如何使VS2010编译器生成AVX代码,但只有当我直接指定AVX内在函数时.对于它工作的SSE,我只使用SSE内在函数,它产生SSE代码,没有任何编译器选项,如/arch:SSE.但对于AVX而言,由于某些原因它不起作用.
你有一个三(或四)个浮点数的向量.总结它们的最快方法是什么?
SSE(movaps,shuffle,add,movd)总是比x87快吗?SSE4.2中的水平加法说明值得吗?移动到FPU的成本是多少,然后是faddp,faddp?什么是最快的特定指令序列?
"尝试安排事情,这样你可以一次总结四个向量"将不被接受作为答案.:-)
我想我应该熟悉x86 SIMD扩展.但在我开始之前,我遇到了麻烦.我无法找到关于哪些仍然相关的良好概述.
几十年来,x86架构积累了大量的数学/多媒体扩展:
较新的超集是旧的超集,反之亦然?或者它们是互补的吗?
有些人已被弃用吗?哪些仍然相关?我听说过"遗留SSE".
有些是互斥的吗?即他们共享相同的硬件部分?
我应该一起使用哪个来最大化现代Intel/AMD CPU的硬件利用率?为了争论,让我们假设我可以找到适当的指令用途...如果没有别的话,用CPU加热我的房子.
想象一下,您希望将一系列x86汇编指令与某些边界对齐.例如,您可能希望将循环对齐到16或32字节的边界,或者将指令打包以使它们有效地放置在uop缓存中或其他任何位置.
实现这一目标的最简单方法是单字节NOP指令,紧接着是多字节NOP.虽然后者通常效率更高,但这两种方法都不是免费的:NOP使用前端执行资源,并且还计入现代x86上的4宽1重命名限制.
另一个选择是以某种方式延长一些指令以获得所需的对齐.如果这样做没有引入新的停顿,它似乎比NOP方法更好.如何在最近的x86 CPU上有效地延长指令?
在理想的世界中,延长技术同时是:
有一种方法不可能同时满足所有上述要点,因此很好的答案可能会解决各种权衡问题.
1 AMD Ryzen的限制为5或6.
我有一个在支持AVX-512的Intel机器上运行的进程,但是这个进程不直接使用任何AVX-512指令(asm或内在函数)并且编译时-mno-avx512f使编译器不插入任何AVX-512指令.
然而,它在减少的AVX turbo频率下无限运行.毫无疑问,有一个AVX-512指令在某个地方偷偷摸摸,通过一个库,(非常不可能)系统调用或类似的东西.
而不是尝试"二进制搜索"AVX-512指令来自哪里,有没有什么方法可以立即找到它,例如,捕获这样的指令?
操作系统是Ubuntu 16.04.
我发现这个职位,说明如何进行转一个8x8矩阵的字节24点的操作,和几个卷轴后有代码实现转置.但是,这种方法没有利用我们可以阻止 8x8转置为4个4x4转置的事实,并且每个转换只能在一个shuffle指令中完成(这篇文章是参考文献).所以我推出了这个解决方案:
__m128i transpose4x4mask = _mm_set_epi8(15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0);
__m128i shuffle8x8Mask = _mm_setr_epi8(0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15);
void TransposeBlock8x8(uint8_t *src, uint8_t *dst, int srcStride, int dstStride) {
__m128i load0 = _mm_set_epi64x(*(uint64_t*)(src + 1 * srcStride), *(uint64_t*)(src + 0 * srcStride));
__m128i load1 = _mm_set_epi64x(*(uint64_t*)(src + 3 * srcStride), *(uint64_t*)(src + …Run Code Online (Sandbox Code Playgroud) 随着AVX的推出,英特尔将VEX编码方案引入了英特尔64和IA-32架构.该编码方案主要用于AVX指令.我想知道是否可以混合使用VEX编码指令和现在称为"传统SSE"的指令.
我问这个问题的主要原因是代码大小.请考虑以下两条说明:
shufps xmm0, xmm0, 0
vshufps xmm0, xmm0, xmm0, 0
Run Code Online (Sandbox Code Playgroud)
我通常使用第一个"广播"标量值到XMM寄存器中的所有位置.现在,指令集表明这两者之间的唯一区别(在这种情况下)是VEX编码的一个清除了YMM寄存器的高位(> = 128).假设我不需要,在这种情况下使用VEX编码版本有什么好处?第一条指令需要4个字节(0FC6C000),第二条指令需要5个(C5F8C6C000).
提前感谢所有答案.
我有一些奇怪的问题,我正在研究一些SSE2和AVX代码.我正在使用GCC构建我的应用程序,运行时cpu特征检测.对象文件使用每个CPU功能的单独标志构建,例如:
g++ -c -o ConvertSamples_SSE.o ConvertSamples_SSE.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -msse
g++ -c -o ConvertSamples_SSE2.o ConvertSamples_SSE2.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -msse2
g++ -c -o ConvertSamples_AVX.o ConvertSamples_AVX.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -mavx
Run Code Online (Sandbox Code Playgroud)
当我第一次启动该程序时,我发现SSE2例程正常,非SSE例程的速度提升(大约快100%).在我运行任何AVX例程之后,完全相同的SSE2例程现在运行得慢得多.
有人可以解释一下这可能是什么原因吗?
在AVX例程运行之前,所有测试都比FPU数学运算快大约80-130%,如此处所示,在AVX例程运行之后,SSE例程要慢得多.
如果我跳过AVX测试程序,我从未看到这种性能损失.
这是我的SSE2例程
void Float_S16(const float *in, int16_t *out, const unsigned int samples)
{
static float ratio = (float)Limits<int16_t>::range() / (float)Limits<float>::range();
static __m128 mul = _mm_set_ps1(ratio);
unsigned int i;
for (i = 0; i < samples - 3; i += 4, …Run Code Online (Sandbox Code Playgroud) 我理解VZEROUPPER在混合SSE和AVX代码时使用很重要,但如果我只使用AVX(和普通的x86-64代码)而不使用任何传统的SSE指令呢?
如果我从不在我的代码中使用单个SSE指令,是否有任何性能原因我需要使用VZEROUPPER?
这假设我没有调用任何外部库(可能使用SSE).