在 SSE2/SSSE3 上转置 8 个 16 位元素寄存器

2023-11-23

(我是 SSE/asm 的新手,如果这是显而易见的或多余的,我深表歉意)

有没有比执行 24 个 unpck[lh]ps 和 8/16+ 混洗以及使用 8 个额外寄存器更好的方法来转置包含 16 位值的 8 个 SSE 寄存器? (注意最多使用 SSSE 3 指令、Intel Merom,又名缺少 SSE4 的 BLEND*。)

假设您有寄存器 v[0-7] 并使用 t0-t7 作为辅助寄存器。在伪内在函数代码中:

/* Phase 1: process lower parts of the registers */
/* Level 1: work first part of the vectors */
/*   v[0]  A0 A1 A2 A3 A4 A5 A6 A7
**   v[1]  B0 B1 B2 B3 B4 B5 B6 B7
**   v[2]  C0 C1 C2 C3 C4 C5 C6 C7
**   v[3]  D0 D1 D2 D3 D4 D5 D6 D7
**   v[4]  E0 E1 E2 E3 E4 E5 E6 E7
**   v[5]  F0 F1 F2 F3 F4 F5 F6 F7
**   v[6]  G0 G1 G2 G3 G4 G5 G6 G7
**   v[7]  H0 H1 H2 H3 H4 H5 H6 H7 */
t0 = unpcklps (v[0], v[1]); /* Extract first half interleaving */
t1 = unpcklps (v[2], v[3]); /* Extract first half interleaving */
t2 = unpcklps (v[4], v[5]); /* Extract first half interleaving */
t3 = unpcklps (v[6], v[7]); /* Extract first half interleaving */
t0 = pshufhw (t0, 0xD8); /* Flip middle 2 high */
t0 = pshuflw (t0, 0xD8); /* Flip middle 2 low */
t1 = pshufhw (t1, 0xD8); /* Flip middle 2 high */
t1 = pshuflw (t1, 0xD8); /* Flip middle 2 low */
t2 = pshufhw (t2, 0xD8); /* Flip middle 2 high */
t2 = pshuflw (t2, 0xD8); /* Flip middle 2 low */
t3 = pshufhw (t3, 0xD8); /* Flip middle 2 high */
t3 = pshuflw (t3, 0xD8); /* Flip middle 2 low */
/*   t0   A0 B0 A1 B1 A2 B2 A3 B3  (A B - 0 1 2 3)
**   t1   C0 D0 C1 D1 C2 D2 C3 D3  (C D - 0 1 2 3)
**   t2   E0 F0 E1 F1 E2 F2 E3 F3  (E F - 0 1 2 3)
**   t3   G0 H0 G1 H1 G2 H2 G3 H3  (G H - 0 1 2 3) */
/* L2 */
t4 = unpcklps (t0, t1);
t5 = unpcklps (t2, t3);
t6 = unpckhps (t0, t1);
t7 = unpckhps (t2, t3);
/*   t4   A0 B0 C0 D0 A1 B1 C1 D1 (A B C D - 0 1)
**   t5   E0 F0 G0 H0 E1 F1 G1 H1 (E F G H - 0 1)
**   t6   A2 B2 C2 D2 A3 B3 C3 D3 (A B C D - 2 3)
**   t7   E2 F2 G2 H2 E3 F3 G3 H3 (E F G H - 2 3) */
/* Phase 2: same with higher parts of the registers */
/*   A    A0 A1 A2 A3 A4 A5 A6 A7
**   B    B0 B1 B2 B3 B4 B5 B6 B7
**   C    C0 C1 C2 C3 C4 C5 C6 C7
**   D    D0 D1 D2 D3 D4 D5 D6 D7
**   E    E0 E1 E2 E3 E4 E5 E6 E7
**   F    F0 F1 F2 F3 F4 F5 F6 F7
**   G    G0 G1 G2 G3 G4 G5 G6 G7
**   H    H0 H1 H2 H3 H4 H5 H6 H7 */
t0 = unpckhps (v[0], v[1]);
t0 = pshufhw (t0, 0xD8); /* Flip middle 2 high */
t0 = pshuflw (t0, 0xD8); /* Flip middle 2 low */
t1 = unpckhps (v[2], v[3]);
t1 = pshufhw (t1, 0xD8); /* Flip middle 2 high */
t1 = pshuflw (t1, 0xD8); /* Flip middle 2 low */
t2 = unpckhps (v[4], v[5]);
t2 = pshufhw (t2, 0xD8); /* Flip middle 2 high */
t2 = pshuflw (t2, 0xD8); /* Flip middle 2 low */
t3 = unpckhps (v[6], v[7]);
t3 = pshufhw (t3, 0xD8); /* Flip middle 2 high */
t3 = pshuflw (t3, 0xD8); /* Flip middle 2 low */
/*   t0   A4 B4 A5 B5 A6 B6 A7 B7  (A B - 4 5 6 7)
**   t1   C4 D4 C5 D5 C6 D6 C7 D7  (C D - 4 5 6 7)
**   t2   E4 F4 E5 F5 E6 F6 E7 F7  (E F - 4 5 6 7)
**   t3   G4 H4 G5 H5 G6 H6 G7 H7  (G H - 4 5 6 7) */
/* Back to first part, v[0-3] can be re-written now */
/* L3 */
v[0] = unpcklpd (t4, t5);
v[1] = unpckhpd (t4, t5);
v[2] = unpcklpd (t6, t7);
v[3] = unpckhpd (t6, t7);
/* v[0] = A0 B0 C0 D0 E0 F0 G0 H0
** v[1] = A1 B1 C1 D1 E1 F1 G1 H1
** v[2] = A2 B2 C2 D2 E2 F2 G2 H2
** v[3] = A3 B3 C3 D3 E3 F3 G3 H3 */
/* Back to second part, t[4-7] can be re-written now... */
/* L2 */
t4 = unpcklps (t0, t1);
t5 = unpcklps (t2, t3);
t6 = unpckhps (t0, t1);
t7 = unpckhps (t2, t3);
/*   t4   A4 B4 C4 D4 A5 B5 C5 D5 (A B C D - 4 5)
**   t5   E4 F4 G4 H4 E5 F5 G5 H5 (E F G H - 4 5)
**   t6   A6 B6 C6 D6 A7 B7 C7 D7 (A B C D - 6 7)
**   t7   E6 F6 G6 H6 E7 F7 G7 H7 (E F G H - 6 7) */
/* L3 */
v[4] = unpcklpd (t4, t5);
v[5] = unpckhpd (t4, t5);
v[6] = unpcklpd (t6, t7);
v[7] = unpckhpd (t6, t7);
/* v[4] = A4 B4 C4 D4 E4 F4 G4 H4
** v[5] = A5 B5 C5 D5 E5 F5 G5 H5
** v[6] = A6 B6 C6 D6 E6 F6 G6 H6
** v[7] = A7 B7 C7 D7 E7 F7 G7 H7 */

每个 unpck* 需要 3 个周期的延迟,或者 2 个周期的延迟(由 Agner 报告)。这会扼杀使用 SSE(在此代码上)带来的大部分性能收益,因为这种寄存器舞蹈几乎每个元素需要一个周期。我试图理解 x264 的 x86 转置的 asm 文件,但未能理解宏。

Thanks!


是的,总共 24 条指令即可完成:

8 x _mm_unpacklo_epi16/_mm_unpackhi_epi16 (PUNPCKLWD/PUNPCKHWD)
8 x _mm_unpacklo_epi32/_mm_unpackhi_epi32 (PUNPCKLDQ/PUNPCKHDQ)
8 x _mm_unpacklo_epi64/_mm_unpackhi_epi64 (PUNPCKLQDQ/PUNPCKHQDQ)

如果您需要更多详细信息,请告诉我,但这相当明显。

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

在 SSE2/SSSE3 上转置 8 个 16 位元素寄存器 的相关文章

  • 一个地址有多少字节? [复制]

    这个问题在这里已经有答案了 在64位机器上 我们知道一个地址是8个字节 然而 我并不完全清楚一个地址中有多少字节的信息 虚拟内存中的每个字节都有一个地址吗 或者内存中的每 64 位都有一个地址 还是取决于架构 如果这取决于架构 那么我应该如
  • 学习 (N)ASM 的最佳资源是什么? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想学习汇编已经有一段时间了 尽管我之前尝试过几次 但我还没有真正能够超越 Hello world 有
  • 从 DX:AX 寄存器转移到单个 32 位寄存器

    我在添加 16 位乘法的乘积时遇到问题 我想将一年 例如 2015 年 乘以 365 为此 我 mov dx 0 to clear the register mov ax cx cx holds the year such as 2015
  • ICC 中的 -O3 会扰乱内在函数,使用 -O1 或 -O2 或相应的手动汇编即可

    这是后续这个问题 http stackoverflow com questions 49791664 o2 in icc messes up assembler fine with o1 in icc and all optimizatio
  • 用 R 将矩阵划分为 N 个大小相等的块

    如何使用 R 将矩阵或数据帧划分为 N 个大小相等的块 我想水平切割矩阵或数据框 例如 给定 r 8 c 10 number of chunks 4 data matrix seq r c nrow r ncol c gt gt gt da
  • PHP清晰度卷积矩阵

    我正在使用一个卷积矩阵 http www php net manual en function imageconvolution php为了锐度PHP GD我想改变清晰度 level 我会去哪里做出改变如果我想做到的话或多或少尖锐 imag
  • 如何在 MacOS 上使用 nasm 进行编译

    我正在尝试在汇编器上编译并链接我的第一个程序 我尝试编译以下代码 include stud io inc global main section text main xor eax eax again PRINT Hello PUTCHAR
  • 如何在R中用随机数填充矩阵?

    expand grid i rexp 5 rate 0 1 它只创建一列 但有什么方法可以轻松地将其乘以 5 列吗 我的意思是 matlab 的做事方式 比如rand exp 0 1 10 20 创建一个指数分布随机数的矩阵 平均值为 0
  • 如何计算汇编中的内存位移?

    我一直在研究 yasm 汇编语言 并生成了一个包含以下内容的列表文件 我需要帮助理解第一列中的内存位移是如何计算的 提前致谢 1 line 1 1 memory asm 2 section data 3 00000000 04000000
  • 使用 ACPI 在 MS-DOS 中关闭计算机

    我在基于 Pentium 的计算机上运行 MS DOS 6 22 主板支持 ACPI 并且想知道是否有一个可以用来关闭计算机的汇编语言例程 或者它是否比那个更难 即主板 具体的 基本上 我想创建一个小程序来从命令行关闭计算机 这是专门为此编
  • intfmt: db "%d", 10, 0 在汇编中的含义

    我最近在我的一个汇编文件的顶部看到了这个 并意识到我在打印整数的过程中花了很长时间使用它 而没有真正意识到它最初来自哪里 在我的基本汇编模板中使用 或 10 0 是什么结尾的意思是 section data intfmt db d 10 0
  • x86 程序集 Pushl/popl 不适用于“错误:后缀或操作数无效”

    我是汇编编程的新手 正在努力解决编程基础 http savannah nongnu org projects pgubook 在带有 GNU 汇编器 v2 20 1 的 Ubuntu x86 64 桌面上 我已经能够汇编 链接执行我的代码
  • 汇编语言程序中连续两次相乘

    我正在使用 8086 模拟器以及 DOSBOX 和 MASM 我知道当我们将 8 位与 8 位相乘时 答案将是 16 位 al 8 bit ax 当我们将 16 位与 16 位相乘时 答案将是 32 位 ax 16 bit dx ax 但如
  • 在 qemu 中将扇区加载到 RAM

    我编写了一个简单的程序 将扇区 扇区编号 2 加载到 RAM 但什么也没打印 首先 我尝试了以下引导扇区代码 org 0x7c00 mov ax 0x1000 ES BX 1000 0000 mov es ax mov bx 0x00 Lo
  • CSR 矩阵 - 矩阵乘法

    我有两个方阵A and B 我必须转换B to CSR Format并确定产品C A B csr C 我在网上找到了很多关于CSR 矩阵 向量乘法 http www mathcs emory edu cheung Courses 561 S
  • 如果默认禁用 A20 线,如何在 0xFFFFFFF0 处访问 BIOS ROM?

    我正在阅读有关 A20 线的信息http wiki osdev org A20 Line http wiki osdev org A20 Line 这似乎表明 A20 线默认被禁用 在Pentium上 如果硬复位后立即输出的地址为0xFFF
  • 如何在汇编中使用 ReadString?

    mov edx offset Prompt1 call WriteString mov ecx 32 mov edx offset String1 call ReadString 现在 我该如何访问String1 如何将其移入寄存器以便对其
  • 如何使 gcc 为 -fpatchable-function-entry 发出多字节 NOP?

    gcc确实有能力使用多字节用于对齐循环和函数的 NOP 然而当我尝试 fpatchable function entry option https gcc gnu org onlinedocs gcc Instrumentation Opt
  • 32位进程在64位操作系统上可以访问多少内存?

    在 Windows 上 正常情况下 32 位进程只能访问 2GB RAM 或通过 boot ini 文件中的特殊开关访问 3GB 在 64 位操作系统上运行 32 位进程时 有多少可用内存 是否有任何特殊的开关或设置可以改变这种情况 默认
  • 使用“const cv::Mat &”、“cv::Mat &”、“cv::Mat”或“const cv::Mat”作为函数参数的区别?

    我已经彻底搜索过 但没有找到一个简单的答案 传递 opencv 矩阵 cv Mat 作为函数的参数 我们传递一个智能指针 我们对函数内部的输入矩阵所做的任何更改也会改变函数范围之外的矩阵 我读到 通过将矩阵作为 const 引用传递 它不会

随机推荐

  • 如何在 .NET Framework 4.7.2 中引用 System.Management.Automation?

    我启动了一个新的 NET Framework 4 7 2 库项目 我需要自动化 PowerShell 脚本 但 Visual Studio 参考中添加 UI 的 框架 选项卡未将 System Management Automation 列
  • Android:ListView 中的 EditText 问题

    我的应用程序中有一个列表视图 它基本上是一个调查问卷 因此用户需要填写一些编辑文本 我遇到过以下问题 某些 EditText 需要数字输入 因此我将相应 xml 类型中的 inputType 设置为数字 但是 当我单击 EditText 时
  • 为什么 Guava 的 TypeToken.getRawType() 返回 Class<?超级 T> 而不是 Class

    来自 Effective Java Second Edition 第 28 条 不要使用通配符类型作为返回类型 这不会为用户提供额外的灵活性 而是会迫使他们在客户端代码中使用通配符类型 public final Class
  • 使用 Nashorn (JSR 223) 和预编译进行 Java 脚本编写

    我通过 JSR 223 使用 Nashorn 来执行用户输入脚本的小片段 public Invocable buildInvocable String script throws ScriptException ScriptEngine e
  • AWS Lambda 和 SNS:跨区域调用 Lambda

    我有一个部署到多个区域的 Lambda 函数 我想向 SNS 发布一条消息来调用这些函数 我使用 aws cli 创建了主题 授予 Lambda 与 SNS 通信的权限 并创建订阅 订阅似乎已成功创建 我可以在 AWS 控制台中看到它 但是
  • 为什么对域名后的第一个斜杠进行 url 编码会破坏 url?

    萨尔维特 我发现某种 url 编码方式会破坏链接 作为记录 2f代表正斜杠字符 现在 考虑一下 原文链接 http dottech org 95285 this is the pacific barreleye a fish with a
  • 方法名称为空,这实际上是做什么的?

    我目前正在自学 Objective C 和 iOS 编程 发现自己由于这个微妙的错误而陷入了无法工作的代码一个小时 考虑以下代码 property strong nonatomic NSString name NSString name r
  • Bootstrap-Datetimepicker 不适用于 jQuery 3

    Bootstrap datetimepicker 不适用于 jQuery 3 1 1 我需要使用相同的 jQuery 库来运行所有其他依赖函数 我遇到同样的错误 input size is not a function TypeError
  • 递归数组类型打字稿

    说我有类型type Atom string boolean number 我想定义一种数组类型 例如 NestedArray Atom a 0 a 1 a n 其中每个a i is an Atom or a NestedArray 这可以在
  • 1093 MySQL 表被指定两次时出错

    我正在尝试更新一些行 我只想更新 ID 0 的行 我收到的错误消息是 1093 表 ch 15 posts 被指定两次 既作为 UPDATE 的目标又作为单独的数据源 这是我正在使用的代码 欢迎大家提出意见 UPDATE ch 15 pos
  • 从基类创建子类的克隆副本

    考虑这种情况 public class Base public int i public class Sub Base public void foo do stuff 然后我想 举个例子Base获取一个克隆实例Sub 在本例中 i 17
  • 这是什么?????!运算符在C中做什么?

    我看到一行C 看起来像这样 ErrorHasOccured HandleError 它编译正确并且似乎运行正常 看起来它正在检查是否发生了错误 如果发生了 它就会处理它 但我不太确定它实际上在做什么或它是如何做的 看起来程序员确实正在尝试表
  • 如何在 Yii2 Active Record 中使用 JOIN 建立关系模型?

    我有 2 张表 分别称为 书籍 和 评论 Books 表与 Reviews 具有一对多关系 我想搜索书籍并按评论对它们进行排序 例如 如果有 10 本书可用 并且书籍在评论中有评论 那么我想使用 WHERE 子句查找所有书籍并计算评论数量
  • 开发人员应该首先考虑可读性还是性能? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 开发人员常常面临着在解决问
  • 如果在pluginManagement下定义插件,maven目标将无法正确执行

    我有 maven jaxb2 plugin 我生成 jaxb 对象并在项目的其他类中引用它 我已将 jaxb 插件和编译器插件放在pluginManagement 标记下 Maven 首先执行编译阶段而不是生成阶段 就好像我删除了plugi
  • 从源字符串中查找多个索引

    基本上我需要执行 String IndexOf 并且需要从源字符串中获取索引数组 有没有简单的方法来获取索引数组 在问这个问题之前 我已经用谷歌搜索了很多 但没有找到解决这个简单问题的简单解决方案 这个扩展方法怎么样 public stat
  • 创建一个带有直角三角形/指针的按钮

    Looking to create this 实现这一目标的最佳方法是什么 IT MUST 我绝对希望将文本保留为文本 因此不使用图像 另外 我希望它可以重复使用 以便我可以在其中放入不同的文本 理想情况下 箭头部分应与文本一样高 很高兴有
  • 使 JButton 不可见但可点击?

    如何在java中制作一个不可见但可点击的JButton button setVisible false 使按钮不可见 但不可点击 是否有任何方法使其不可见 但可点击 我尝试这样做 button setVisible false button
  • Eclipse:编辑源代码并继续调试

    我正在使用 Eclipse IDE Helios 版本 在Eclipse中调试时 是否可以编辑源代码并继续调试 例如我有这个文件 在调试时 当我尝试在调试期间修改 a4 值时 它没有反映 public class Tes public st
  • 在 SSE2/SSSE3 上转置 8 个 16 位元素寄存器

    我是 SSE asm 的新手 如果这是显而易见的或多余的 我深表歉意 有没有比执行 24 个 unpck lh ps 和 8 16 混洗以及使用 8 个额外寄存器更好的方法来转置包含 16 位值的 8 个 SSE 寄存器 注意最多使用 SS