加载 128 位混合浮点 + 整数数据?
Posted
技术标签:
【中文标题】加载 128 位混合浮点 + 整数数据?【英文标题】:Loading 128 bits of mixed float+int data? 【发布时间】:2015-06-07 13:00:56 【问题描述】:我有一个结构如下:
static constexpr uint64_t emptyStructValue 0 ;
union MyStruct
explicit MyStruct(uint64_t comp) : composite(comp)
struct
int16_t a;
bool b;
bool c;
float d;
;
uint64_t composite = 0;
bool hasValue()
return composite != emptyStructValue;
;
我在另一个对象中有两个这样的结构:
class B
Struct s1;
Struct s2;
;
我想知道,给定 B 类型的对象,我如何将所有 128 位加载到 SSE 寄存器中并检查是否设置了单个位?
我找到了_mm_loadu_si128()
,但我的数据混合了整数和浮点数?
【问题讨论】:
您只想检查是否至少设置了一位?只是为了确定,在花车上做这个时你期望什么?对于整数(和二进制补码),它与检查它是否不为 0 相同,但浮点数更复杂 => 究竟是什么目的? 你的结构实例总是包含所有 4 个变量和一些值?它不能是空的。编辑:工会的东西也不会让它变空。 "All 64 bits zero" - 你假设bool
有 7 个填充位,所有这些都是零。
你的问题是 128 位,你的评论是 64。
您应该将您的bool
s 设为int8_t
s,以便我们保证尺寸和价值。但是,暂且不说:是的,您可以像这样加载两个 64 位联合,无论它们是整数数据和浮点数的混合;既然你有 AVX,你很可能也有 SSE4.1,在这种情况下,pcmpeqq
指令(可通过__m128i _mm_cmpeq_epi64(__m128i, __m128i)
访问)正是你想要的。
【参考方案1】:
实际上,如果(sizeof(B) == 2*sizeof(uint64_t)
,那么我认为没有理由不执行您的建议。但如果速度很重要(看起来很重要),您应该将 B
对象与 128 位边界对齐,这样您就可以使用 _mm_load_si128
而不是 _mm_loadu_si128
。
编辑添加:事实上,在 64 位模式下,使用常规操作码可能更快。比如:
mov rax,[rsi]
or rax,[rsi+8]
jnz BitSet
即使在 32 位模式下,它也可能会更快。您将不得不进行实验。
【讨论】:
在栈上创建 B,对齐到 128 位。然后 __declspec(align(128)) B b; B* bptr = &b; __m128i intrinreg = _mm_load_si128(reinterpret_cast<__m128i>(bptr));但不确定如何将 __m128i 与数字零进行比较? @user997112:嗯,好问题。我看不出有什么办法。也许最好的方法就是if (s1.composite == 0 && s2.composite == 0)
。
@user997112 There's an SO question about just that,如果pcmpeqq
对你来说不够好。
@IwillnotexistIdonotexist: pcmpeqq
没有设置任何标志,它只是相应地设置目标 SSE 寄存器。这会让你回到你开始的地方。
pcmpeqq
需要单独测试 64 位整数是否相等。当然,之后跟着pmovmaskb
提取比较结果;如果与零的比较都不为真,则后面的指令将返回 0x0000
,如果其中一个为真,则返回 0xFF00
或 0x00FF
,如果两者都为真,则返回 0xFFFF
。以上是关于加载 128 位混合浮点 + 整数数据?的主要内容,如果未能解决你的问题,请参考以下文章