正确使用加载/存储

Posted

技术标签:

【中文标题】正确使用加载/存储【英文标题】:Use load/store correctly 【发布时间】:2015-07-01 15:27:46 【问题描述】:

如何使用加载/存储来正确进行对齐的int16_t 字节交换?

void byte_swapping(uint16_t* dest, const uint16_t* src,
                              size_t count) 
    __m128i _s, _d;
    for (uint16_t const * end(dest + count); dest != end; dest += 8, src += 8)
    
        _s = _mm_load_si128((__m128i*)src);
        _d = _mm_or_si128(_mm_slli_epi16(_s, 8), _mm_srli_epi16(_s, 8));
        _mm_store_si128((__m128i*) dest, _d);
    

【问题讨论】:

您遇到了什么具体问题?如果只是缓冲区没有正确对齐,那么要么修复对齐,要么使用_mm_loadu_si128/_mm_storeu_si128 我试过 _mm_loadu_si128/_mm_storeu_si128 ,它在 VS 2015 中也崩溃了。或者任何其他方式来编写这个 16 字节交换 uisng SSE 内在函数? 从您向我们展示的内容来看,该代码看起来不错 - 您可以发布 MCVE 吗? 那么从 VS 2015 break 开始,你认为问题是什么? 如果没有 MCVE,几乎不可能为您提供帮助。我看到的唯一明显错误是,如果 count 不是 8 的倍数,您的例程将失败 - 这似乎就是您的特定示例崩溃的原因,因为 172 不是 8 的倍数。 【参考方案1】:

count 不是 8 的倍数,或者srcdest 不是 16 字节对齐时,您的代码将失败。

这是您的代码的固定(和测试)版本:

void byte_swapping(uint16_t* dest, const uint16_t* src, size_t count)

    size_t i;
    for (i = 0; i + 8 <= count; i += 8)
    
        __m128i s = _mm_loadu_si128((__m128i*)&src[i]);
        __m128i d = _mm_or_si128(_mm_slli_epi16(s, 8), _mm_srli_epi16(s, 8));
        _mm_storeu_si128((__m128i*)&dest[i], d);
    
    for ( ; i < count; ++i) // handle residual elements
    
        uint16_t w = src[i];
        w = (w >> 8) | (w << 8);
        dest[i] = w;
    

【讨论】:

谢谢保罗。让我今晚试试。实际上我们正在开发一个 xbox 360 模拟器,进展非常顺利。 github.com/benvanik/xenia 它接近并且看起来更好,但它以某种方式像这样被切断i.stack.imgur.com/pT9GP.jpg 好的 - 我怀疑错误存在于其他地方 - 您可以通过将 byte_swapping 替换为简单的标量实现来证明这一点 - 我希望您会看到相同的结果。 好的 - 你能在你的问题中包含标量版本吗? for (size_t i = 0; i > 8) & 0xff) | ((src[i]

以上是关于正确使用加载/存储的主要内容,如果未能解决你的问题,请参考以下文章

托管在通过 Azure Front Door 访问的存储帐户上的静态网站未正确加载

将文件从 Azure Blob 存储加载到 Azure SQL DB:错误代码 86 指定的网络密码不正确

正确使用 Classloader(尤其是在 Android 中)

在 Laravel 中从数据库存储和加载 JSON 的最佳方法

持久存储条目仍然存在,但重建时数据为空

iOS 应用程序的存档数据无法正确加载