我已经开始使用SSE优化我的代码.基本上它是一个光线跟踪器,通过在__m128数据类型x,y,z中存储坐标,一次处理4条光线(四条光线的坐标按轴分组).但是,我有一个分支语句,可以防止除以零,我似乎无法转换为SSE.连续这是:
const float d = wZ == -1.0f ? 1.0f/( 1.0f-wZ) : 1.0f/(1.0f+wZ);
Run Code Online (Sandbox Code Playgroud)
其中wZ是z坐标,需要对所有四条射线进行计算.
我怎么能把它翻译成SSE?
我一直在尝试使用SSE等于比较如下(现在wz属于__m128数据类型,包含四条光线中每条光线的z值):
_mm_cmpeq_ps(_mm_set1_ps(-1.0f) , wZ )
Run Code Online (Sandbox Code Playgroud)
然后使用它来识别wZ [x] = -1.0的情况,取这个情况的绝对值,然后继续计算正常.
但是,我在这方面没有取得多大成功.
我正在尝试使用SSE优化立方体功能
long cube(long n)
{
return n*n*n;
}
Run Code Online (Sandbox Code Playgroud)
我试过这个:
return (long) _mm_mul_su32(_mm_mul_su32((__m64)n,(__m64)n),(__m64)n);
Run Code Online (Sandbox Code Playgroud)
而且表现更差(是的,我从未对sse做过任何事情).
是否有可以提高性能的SSE功能?或者是其他东西?
cat/proc/cpuinfo的输出
processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 15 model name : Intel(R) Xeon(R) CPU 3070 @ 2.66GHz stepping : 6 cpu MHz : 2660.074 cache size : 4096 KB physical id : 0 siblings : 2 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : …
请考虑以下代码段:
double dot(double* a, double* b, int n) {
double sum = 0;
for (int i = 0; i < n; ++i) sum += a[i] * b[i];
return sum;
}
Run Code Online (Sandbox Code Playgroud)
如何使用内在函数或汇编程序加快速度?
笔记:
n 几百.是否有单个 SSE指令将两个寄存器的高字和低字交错到另一个寄存器中?例如:
r[63-0] = a[64-127]
r[64-127] = b[63-0]
Run Code Online (Sandbox Code Playgroud) 从未接触过微软的Windows 7计算器程序.令人惊讶的是,计算器程序的精度高达32位小数.Microsoft肯定不使用MPIR或其他将数字视为字符串的库.计算器程序是否使用内在函数?
我想编写一个程序,使用这些内部函数计算一个双精度到32位小数的日志.
我有一个繁重的数字运算程序,可以进行图像处理.它主要是卷积.它是用C++编写的,用Mingw GCC 4.8.1编译.我在配备Intel Core i7 4900MQ(SSE高达SSE4.2和AVX2)的笔记本电脑上运行它.
当我告诉GCC使用SSE优化(使用-march = native -mfpmath = sse -msse2)时,与使用默认的x87 FPU相比,我看不到加速.
当我使用双打而不是浮动时,没有减速.
我的理解是,当使用浮动而不是双重时,SSE应该给我2倍的加速.我错了吗?
我在C中使用向量内部操作编写了一个简单的向量添加程序.这里我加载2个向量并添加它们,最后将结果向量存储回全局内存.
当我检查汇编代码时,它具有以下顺序的指令
movdqa 0(%rbp,%rax), %xmm7
paddd (%r12,%rax), %xmm7
movdqa %xmm7, (%rbx,%rax)
Run Code Online (Sandbox Code Playgroud)
如您所见,它只将paddd指令的一个操作数移动到寄存器(xmm7).在paddd指令中,第一个操作数指的是全局存储器中的地址,而不是先将寄存器移到寄存器中.
这是否意味着当paddd执行时,它首先从全局内存中移动到寄存器,然后添加两个寄存器中的操作数?这相当于以下代码序列
movdqa 0(%rbp,%rax), %xmm7
movdqa 0(%r12,%rax), %xmm8
paddd %xmm8, %xmm7
movdqa %xmm7, (%rbx,%rax)
Run Code Online (Sandbox Code Playgroud)
如果您需要更多信息(如可编译程序),请告诉我们,以便您自己生成程序集.
我想加速一个简单的积分器,它根据位置和速度描述一组无质量粒子.我不是SSE/AVX专家,但我觉得有趣的是SIMD扩展可以在这里产生什么.
许多论文建议使用数组结构:
struct {
static float2 xy[OUGHTA_BE_ENOUGH];
static float2 vxvy[OUGHTA_BE_ENOUGH];
} Particles;
// in main loop:
Particles.xy[i] += time_delta * Particles.vxvy[i];
Run Code Online (Sandbox Code Playgroud)
但是,对于许多应用来说,相反的方法是有益的:
struct {
float2 xy;
float2 vxvy;
} Particle;
// in main loop:
particles[i].xy += time_delta * particles[i].vxvy;
Run Code Online (Sandbox Code Playgroud)
虽然我模糊地理解要搜索什么来矢量化数组结构版本,但我怀疑有没有办法将SIMD与结构数组版本一起使用,因为字段访问或"调配".
是否有任何技术可以使用SIMD进行上述计算,或者我错过了内在函数?
在研究从yuv到ffb的ffmpeg转换时,我遇到了在程序集中实现的方程,yuv2rgb_template.c位于ffmpeg / libswscale / x86中。
我想知道packuswb指令的工作原理吗?Google说:
使用无符号饱和度将mm中的4个有符号字整数和mm / m64中的4个有符号字整数转换为mm中的8个无符号字节整数。
DEST[7:0] ? SaturateSignedWordToUnsignedByte DEST[15:0];
DEST[15:8] ? SaturateSignedWordToUnsignedByte DEST[31:16];
DEST[23:16] ? SaturateSignedWordToUnsignedByte DEST[47:32];
DEST[31:24] ? SaturateSignedWordToUnsignedByte DEST[63:48];
DEST[39:32] ? SaturateSignedWordToUnsignedByte SRC[15:0];
DEST[47:40] ? SaturateSignedWordToUnsignedByte SRC[31:16];
DEST[55:48] ? SaturateSignedWordToUnsignedByte SRC[47:32];
DEST[63:56] ? SaturateSignedWordToUnsignedByte SRC[63:48];
Run Code Online (Sandbox Code Playgroud)
由于我不知道Assembly x86,因此甚至很难对其进行仿真或调试当前代码。
我想知道它们如何适合8位中的16位?
MOVHPD将xmm寄存器的高位四字提取到内存中。
PEXTRQ提取xmm寄存器的高位四字并将其放入整数寄存器(仅整数)。
SHUFPD随机播放。
VPSLLDQ使高位四字清零。
是否有指令将浮点值从xmm寄存器的高位四字移动到同一xmm寄存器或另一个xmm寄存器的低位四字?还是我总是必须经过内存(添加额外的周期)?
更新:根据以下@fuz和@Peter Cordes的评论,这是我所做的。这将分别为xmm0的上下四位数调用舍入函数;由于特殊的舍入参数,必须为每个qword分别调用该函数,因此它不能是SIMD指令。目标是将xmm0中的每个qword取整并将结果放入xmm11中。
movapd xmm2,xmm0 ;preserve both qwords of xmm0
call Round
movsd [scratch_register+0],xmm0 ; write low qword to memory
movhlps xmm0,xmm2
call Round
movsd [scratch_register+8],xmm0 ; write low qword to memory
movupd xmm11,[scratch_register]
Run Code Online (Sandbox Code Playgroud)
更新#2:@Peter Cordes显示了如何在没有内存的情况下执行此操作:
movhlps xmm2, xmm0 ; extract high qword for later
call Round ; round the low qword
movaps xmm3, xmm0 ; save the result
movaps xmm0, xmm2 ; set up the arg
call Round ; round the high qword
movlhps xmm3, …Run Code Online (Sandbox Code Playgroud) sse ×10
assembly ×6
c++ ×4
avx ×3
c ×2
x86-64 ×2
dot-product ×1
ffmpeg ×1
gcc ×1
intrinsics ×1
nasm ×1
optimization ×1
performance ×1
simd ×1
x86 ×1
x87 ×1