cha*_*255 5 c assembly gcc sse simd
我正在创建一个结构来在图像中存储单个RGB像素.
struct Pixel
{
// color values range from 0.0 to 1.0
float r, g, b;
}__attribute__((aligned(16));
Run Code Online (Sandbox Code Playgroud)
我想使用128位SSE指令来执行添加,乘法等操作.这样我就可以同时对所有3个颜色通道执行操作.因此,我的SSE寄存器中的第一个打包浮点数将是红色,然后是绿色,然后是蓝色,但我不太确定将进入我的第四个寄存器.我真的不在乎额外的32位填充中的哪些位.当我将一个像素加载到SSE寄存器中时,我会想象它包含零或垃圾值.这有问题吗?我应该添加第四个alpha通道,即使我真的不需要吗?我认为这是一个问题的唯一方法是,如果我除以一个像素,并且在第四个点中有一个零值,或者我正在使用一个负数的根等等.
对于未初始化的值,整数运算完全没有问题,因为延迟从不依赖于数据.浮点不同.一些FPU减慢了非正规数,NaN和无穷大(在任何一个向量元素中).
在使用非正常输入/输出和FP下溢/溢出进行数学运算时,英特尔Nehalem和更早的速度会慢下来.Sandybridge有一个很好的FPU,可以为任何输入提供快速加/ 减(根据Agner Fog的指令表),但乘法仍然可以放慢速度.
使用零可以添加/ sub/multiply,但是可能代表NaN或其他东西的未初始化垃圾可能存在问题.
除非你没有除以零,否则要小心.这甚至可能引发FPU异常,具体取决于硬件设置.
所以是的,保持未使用的元素归零可能是一个好主意.根据你最初的生成方式,这可能相当便宜.(例如,movd/pinsrd/pinsrd(或insertps)将三个32位元素放入一个向量中,初始movd将高位置为96b.)
一种解决方法可能是在第4个元素中存储蓝色通道的第二个副本.(或者最方便在那里洗牌的东西.)你可以用movsldup
(SSE3)/ 加载向量movlps
.之后movsldup
,您的注册将成立{ b b r r }
. movlps
将重新加载较低的64位,所以你有{ b b g r }
.(这相当于movsd
,BTW.)或者如果shuffle端口不如加载端口忙,则执行一次16B加载然后shufps.(movsldup
在Intel CPU上是一个在加载端口上运行的单个uop,即使它内置了重复项.)
另一种选择是将像素打包成12个字节,因此16B负载将获得下一个像素的一个分量.根据你正在做的事情,重叠商店会破坏下一个像素的一个元素可能会或可能不会.在存储当前值之前加载下一个像素可以解决某些操作的问题.缓存或带宽限制非常容易,因此以偶然的缓存行拆分加载/存储的低成本节省1/4空间可能是值得的.