打乱 SSE 寄存器中的偶数和奇数值

2024-03-02

我用 16 位值加载两个 SSE 128 位寄存器。这些值按以下顺序排列:

src[0] = [E_3, O_3, E_2, O_2, E_1, O_1, E_0, O_0]
src[1] = [E_7, O_7, E_6, O_6, E_5, O_5, E_4, O_4]

我想要实现的是这样的命令:

src[0] = [E_7, E_6, E_5, E_4, E_3, E_2, E_1, E_0]
src[1] = [O_7, O_6, O_5, O_4, O_3, O_2, O_1, O_0]

您知道是否有一个好的方法可以做到这一点(通过使用 SSE 内在函数直至 SSE 4.2)?

我现在陷入困境,因为我无法在 128 位寄存器的上半部分和下半部分之间洗牌 16 位值。我只找到了_mm_shufflelo_epi16 and _mm_shufflehi_epi16内在函数。

Update:

感谢 Paul,我考虑过使用 epi8 内在函数来表示 16 位值。

我的解决方案如下:

shuffle_split = _mm_set_epi8(15, 14, 11, 10,  7,  6,  3,  2, 13, 12,  9,  8,  5,  4,  1,  0);

xtmp[0] = _mm_load_si128(src_vec);
xtmp[1] = _mm_load_si128(src_vec+1);
xtmp[0] = _mm_shuffle_epi8(xtmp[0], shuffle_split);
xtmp[1] = _mm_shuffle_epi8(xtmp[1], shuffle_split);

xsrc[0] = _mm_unpacklo_epi16(xtmp[0], xtmp[1]);
xsrc[0] = _mm_shuffle_epi8(xsrc[0], shuffle_split);
xsrc[1] = _mm_unpackhi_epi16(xtmp[0], xtmp[1]);
xsrc[1] = _mm_shuffle_epi8(xsrc[1], shuffle_split);

还有更好的解决方案吗?


上交所的排列并不容易。有多种方法可以通过不同的指令组合来实现相同的结果。不同的组合可能需要不同数量的指令、寄存器或存储器访问。我不想手动解决这样的难题,我更喜欢看看 LLVM 编译器做了什么,所以我用 LLVM 的中间语言编写了您想要的排列的简单版本,它利用了极其灵活的向量洗牌指令:

define void @shuffle_even_odd(<8 x i16>* %src0) {
  %src1 = getelementptr <8 x i16>* %src0, i64 1
  %a = load <8 x i16>* %src0, align 16
  %b = load <8 x i16>* %src1, align 16
  %x = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
  %y = shufflevector <8 x i16> %a, <8 x i16> %b, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
  store <8 x i16> %x, <8 x i16>* %src0, align 16
  store <8 x i16> %y, <8 x i16>* %src1, align 16
  ret void
}

使用 LLVM IR-to-ASM 编译器对其进行编译:llc shuffle_even_odd.ll -o shuffle_even_odd.s你会得到类似以下 x86 程序集的内容:

movdqa  (%rdi), %xmm0
movdqa  16(%rdi), %xmm1
movdqa  %xmm1, %xmm2
pshufb  LCPI0_0(%rip), %xmm2
movdqa  %xmm0, %xmm3
pshufb  LCPI0_1(%rip), %xmm3
por %xmm2, %xmm3
movdqa  %xmm3, (%rdi)
pshufb  LCPI0_2(%rip), %xmm1
pshufb  LCPI0_3(%rip), %xmm0
por %xmm1, %xmm0
movdqa  %xmm0, 16(%rdi)

我排除了上面 LCPIO_* 引用的常量数据部分,但这大致翻译为以下 C 代码:

void shuffle_even_odd(__m128i * src) {
    __m128i shuffle0 = _mm_setr_epi8(128, 128, 128, 128, 128, 128, 128, 128, 2, 3, 6, 7, 10, 11, 14, 15);
    __m128i shuffle1 = _mm_setr_epi8(2, 3, 6, 7, 10, 11, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128);
    __m128i shuffle2 = _mm_setr_epi8(128, 128, 128, 128, 128, 128, 128, 128, 0, 1, 4, 5, 8, 9, 12, 13);
    __m128i shuffle3 = _mm_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, 128, 128, 128, 128, 128, 128, 128, 128);
    __m128i a = src[0];
    __m128i b = src[1];
    src[0] = _mm_or_si128(_mm_shuffle_epi8(b, shuffle0), _mm_shuffle_epi8(a, shuffle1));
    src[1] = _mm_or_si128(_mm_shuffle_epi8(b, shuffle2), _mm_shuffle_epi8(a, shuffle3));
}

这只是 4 个随机播放和 2 个按位或指令。我怀疑这些按位指令可以比您建议的解包指令更有效地在 CPU 管道中进行调度。

您可以在 LLVM 下载页面的“Clang Binaries”包中找到“llc”编译器:http://www.llvm.org/releases/download.html http://www.llvm.org/releases/download.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

打乱 SSE 寄存器中的偶数和奇数值 的相关文章

随机推荐

  • 将 abel 包裹在复合材料中

    I have ScrolledComposite只允许垂直滚动 heighthint 400 在这个 ScrolledComposite 中 我还有另一个CompositeA 滚动高度可能超过 400 来存储所有其他小部件 我有一个很长的标
  • PIL ValueError:图像数据不足?

    当我尝试从 URL 获取图像并将其响应中的字符串转换为Image在 App Engine 内 from google appengine api import urlfetch def fetch img url try result ur
  • ConcurrentQueue 保存对象的引用或值? “内存不足”异常

    排队到 ConcurrentQueue 的对象是被复制到队列还是仅复制到它们的引用 我不明白任何场景 解释 我这样定义了一个 ConcurrentQueue BufferElement is a class I created privat
  • 可观察队列?

    是否有人编写了实现 INotifyCollectionChanged 的 Net 通用队列版本 或者是否已经在 Net 框架深处隐藏了某个版本 快速搜索没有显示任何结果 但接口很简单 扩展 Queue 类并添加对该接口的支持几乎是微不足道的
  • Dropbox SDK 401 错误

    我正在使用 Dropbox SDK 并且已将其设置为应用程序只能访问 Apps MyAPP 文件夹 我正在测试它并在线删除了该文件夹 现在 当我在应用程序中而不是要求重新链接 Dropbox 时 它会给我一个 401 错误 我不知道为什么它
  • Docker 在构建期间不会创建目录

    第一次尝试使用 Docker 在我的 Dockerfile 中执行以下步骤来创建目录 但是当我运行容器时 该目录不存在 FROM ubuntu MAINTAINER AfterWorkGuinness RUN apt get update
  • actix-web 中“扩展”的作用是什么?

    我想弄清楚如何Extension https docs rs actix web 3 3 2 actix web dev struct Extensions htmls 创建于Actix 网络 https crates io crates
  • 无法将焦点设置在 Windows 窗体文本框上

    当选项卡页首次出现时 我似乎无法在文本框中获得输入焦点 我正在使用 Windows 窗体 VB NET 3 5 我在选项卡页的面板上有一个文本框 我希望当选项卡页出现时焦点位于文本框上 我希望用户能够立即开始在聚焦的文本框中键入内容 而无需
  • 如何在 iOS 中更改 ePub 图书的字体颜色和字体样式?

    我创建了支持 pdf 和 ePub 格式的书籍应用程序 在该应用程序中 pdf 仅显示为图像 而 ePub 在 Web 视图中打开 因为 EPUB 只是存储在带有 XML 清单的 zip 文件中的 XHTML 现在 我想改变字体样式 and
  • django 中 settings.py 中的密钥中的“Django-insecure”

    创建新项目后django admin startproject my settings py包含 SECRET KEY django insecure
  • 当 Task.Status 更改为正在运行时,有没有办法收到通知?

    我正在编写一个运行任务并基于通知的类this https msdn microsoft com en us magazine dn605875 aspx 我想不出解决方案的一个问题是如何在 Task Status 离开时发出通知TaskSt
  • 如何在Java、SQL、ORM中使用money数据类型

    在 Java 应用程序中使用货币数据类型的最佳实践是什么 钱应该是双变量吗 四舍五入 货币等又如何呢 有专门的图书馆吗 最流行数据库中的 ORM 和 SQL 又如何呢 据我所知 并非所有 SQL 引擎中都是 Money 数据类型 在这种情况
  • 如果值为负数,如何更改文本颜色?

    我正在开发一个网络应用程序 它可以在整数之间进行加法 我有两个函数叫做num1 and num2 获取两个整数作为用户的输入 如果两个整数之和为负数 我想更改结果输出文本颜色 我如何使用 JavaScript 来做到这一点 我看过很多 jQ
  • Spring MVC: 标签之间的区别? [复制]

    这个问题在这里已经有答案了 前几天开始研究这个Spring Hello World教程 http viralpatel net blogs spring 3 mvc create hello world application spring
  • CSS渐变棋盘图案

    I want to create a checkerboard pattern using gradients I ve found an example and modified it to my needs however it onl
  • 如何在 Mac 上通过终端访问 XAMPP/Lampp 文件夹

    我最近开始在 Mac 上使用 XAMPP 它在 共享 下安装了 lampp 文件夹 并在 Finder 中显示为 IP 地址 因此 我可以通过 Finder 访问这些文件 但无法通过终端 cd 进入该文件夹 共享文件夹根本不可见 我尝试 V
  • 无法通过 docker-letsencrypt-nginx-proxy-companion 启用 ssl

    我想通过以下方式启用 ssldocker letsencrypt nginx proxy companion 这是 docker compose yml version 3 3 services nginx proxy image jwil
  • 返回选定的指定列

    我想从某个 Blob 表中仅选择几列 我有以下字段 Id RowVersion Size Signature Blob 我只想选择前四个 我这样做 gt 是一个错误的地方 public List
  • 从 http 而不是 https 加载图像时出现 403 错误

    我的问题类似于this one https stackoverflow com questions 22958559 403 when trying to download a remote image 但我只使用 html 和 javas
  • 打乱 SSE 寄存器中的偶数和奇数值

    我用 16 位值加载两个 SSE 128 位寄存器 这些值按以下顺序排列 src 0 E 3 O 3 E 2 O 2 E 1 O 1 E 0 O 0 src 1 E 7 O 7 E 6 O 6 E 5 O 5 E 4 O 4 我想要实现的是