加载 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。 您应该将您的bools 设为int8_ts,以便我们保证尺寸和价值。但是,暂且不说:是的,您可以像这样加载两个 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 &amp;&amp; s2.composite == 0) @user997112 There's an SO question about just that,如果pcmpeqq 对你来说不够好。 @IwillnotexistIdonotexist: pcmpeqq 没有设置任何标志,它只是相应地设置目标 SSE 寄存器。这会让你回到你开始的地方。 pcmpeqq 需要单独测试 64 位整数是否相等。当然,之后跟着pmovmaskb提取比较结果;如果与零的比较都不为真,则后面的指令将返回 0x0000,如果其中一个为真,则返回 0xFF000x00FF,如果两者都为真,则返回 0xFFFF

以上是关于加载 128 位混合浮点 + 整数数据?的主要内容,如果未能解决你的问题,请参考以下文章

AVX/SSE 将浮点符号掩码转换为 __m128i

Mysql数据类型之浮点与二进制型数据使用案例总结

PAT-混合类型数据格式化输入

Mysql数据类型之整数型的一些细节你get到了吗?

java运算疑惑 整型和浮点型混合运算

[PTA]7-6 混合类型数据格式化输入