可以使用 movss 指令替换整数数据吗?
Can a movss instruction be used to replace integer data?
由于我只能使用 SSE 和 SSE2 指令的限制,我需要用另一个向量中的 0 元素替换 4 元素向量 __m128i 的最低有效 (0) 元素。
对于浮点向量,任务很简单 - 可以使用 _mm_move_ss() 内在函数将元素替换为另一个向量中的 0 元素。生成一条movss指令,效率很高
使用两个转换内在函数,还可以说服编译器使用单个 SSE movss 指令来移动整数数据。源代码最终看起来像这样:
__m128i NewVector = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(Take3FromThisVector),
_mm_castsi128_ps(Take1FromThisVector)));
它看起来有点乱,但是只要有适当的注释就可以接受,尤其是因为它生成的指令最少。在其典型用途中,所有内容都经过优化以放在 xmm 寄存器中。
我的问题是:
因为它是一条 movss 指令,其中 "ss" 表示单精度浮点数,让它移动可能包含一些 "special" 或 "illegal"(对于浮点)任意向量位置的位组合?
显而易见的替代方案(我也实施并测试过)是将第一个向量与掩码进行 AND 运算,然后在第二个向量中进行 OR 运算,该向量仅包含最低有效元素中的一个值,所有其他元素均为零。可以想象,这会生成更多指令。
我已经测试了我上面展示的转换方法,它似乎没有引起任何问题,但我特别注意到没有内在的 provided 对整数数据执行相同的操作。似乎英特尔会提供一个,如果它对整数数据同样好——例如 _mm_move_epi32 或类似的。所以我怀疑这是否是个好主意。
我进行了一些搜索,例如 "can a movss instruction cause a floating point exception",但没有找到任何可以回答我的问题的信息。
提前感谢您愿意分享的知识。
-诺尔
类型 __m128
和 __m128i
可以互换。强制转换的主要原因是让您的意图更清晰(并让您的编译器满意)。演员表本身不会生成任何额外的程序集。
_mm_move_ss
operation 直接描述了结果中的哪些位。
如果单精度浮点数的位组合无效,只有当您尝试在浮点计算中使用结果值时才会出现问题。
是的,可以对整数数据使用 movss xmm, xmm
之类的 FP 洗牌。 insn 参考手册告诉你它不能引发 FP 数字异常;只有实际的 FP 数学指令才能做到这一点。所以继续投吧。
在大多数 uarche 中,对整数数据使用 FP 混洗甚至没有绕过延迟(但在 FP 数学指令之间使用整数混洗有额外的延迟)。
Agner Fog's "optimizing assembly" guide has a great section on what instructions are useful for different kinds of data movement (broadcasts, merging, etc.) See also the x86 标记 wiki 以获得更多好的链接。
没有整数内在的原因是 SSE2 movd
整数指令将目标的高位字节置零,就像 movss
用作加载,但不像寄存器之间的 movss
.
Intel 的矢量指令集以其不一致和非正交性着称,尤其是。最早的版本(如 SSE1)。 SSE4.1填补了很多空白,但仍有明显的缺失。
由于我只能使用 SSE 和 SSE2 指令的限制,我需要用另一个向量中的 0 元素替换 4 元素向量 __m128i 的最低有效 (0) 元素。
对于浮点向量,任务很简单 - 可以使用 _mm_move_ss() 内在函数将元素替换为另一个向量中的 0 元素。生成一条movss指令,效率很高
使用两个转换内在函数,还可以说服编译器使用单个 SSE movss 指令来移动整数数据。源代码最终看起来像这样:
__m128i NewVector = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(Take3FromThisVector),
_mm_castsi128_ps(Take1FromThisVector)));
它看起来有点乱,但是只要有适当的注释就可以接受,尤其是因为它生成的指令最少。在其典型用途中,所有内容都经过优化以放在 xmm 寄存器中。
我的问题是:
因为它是一条 movss 指令,其中 "ss" 表示单精度浮点数,让它移动可能包含一些 "special" 或 "illegal"(对于浮点)任意向量位置的位组合?
显而易见的替代方案(我也实施并测试过)是将第一个向量与掩码进行 AND 运算,然后在第二个向量中进行 OR 运算,该向量仅包含最低有效元素中的一个值,所有其他元素均为零。可以想象,这会生成更多指令。
我已经测试了我上面展示的转换方法,它似乎没有引起任何问题,但我特别注意到没有内在的 provided 对整数数据执行相同的操作。似乎英特尔会提供一个,如果它对整数数据同样好——例如 _mm_move_epi32 或类似的。所以我怀疑这是否是个好主意。
我进行了一些搜索,例如 "can a movss instruction cause a floating point exception",但没有找到任何可以回答我的问题的信息。
提前感谢您愿意分享的知识。
-诺尔
类型 __m128
和 __m128i
可以互换。强制转换的主要原因是让您的意图更清晰(并让您的编译器满意)。演员表本身不会生成任何额外的程序集。
_mm_move_ss
operation 直接描述了结果中的哪些位。
如果单精度浮点数的位组合无效,只有当您尝试在浮点计算中使用结果值时才会出现问题。
是的,可以对整数数据使用 movss xmm, xmm
之类的 FP 洗牌。 insn 参考手册告诉你它不能引发 FP 数字异常;只有实际的 FP 数学指令才能做到这一点。所以继续投吧。
在大多数 uarche 中,对整数数据使用 FP 混洗甚至没有绕过延迟(但在 FP 数学指令之间使用整数混洗有额外的延迟)。
Agner Fog's "optimizing assembly" guide has a great section on what instructions are useful for different kinds of data movement (broadcasts, merging, etc.) See also the x86 标记 wiki 以获得更多好的链接。
没有整数内在的原因是 SSE2 movd
整数指令将目标的高位字节置零,就像 movss
用作加载,但不像寄存器之间的 movss
.
Intel 的矢量指令集以其不一致和非正交性着称,尤其是。最早的版本(如 SSE1)。 SSE4.1填补了很多空白,但仍有明显的缺失。