- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要从每 24 位输入中解压缩两个 16 位值。 (3 字节 -> 4 字节)。我已经用天真的方法做到了,但我对性能不满意。
例如InBuffer是__m128i
:
value1 = (uint16_t)InBuffer[0:11] // bit-ranges
value2 = (uint16_t)InBuffer[12:24]
value3 = (uint16_t)InBuffer[25:36]
value4 = (uint16_t)InBuffer[37:48]
... for all the 128 bits.
解包后,值应该存储在__m256i变量中。
如何使用 AVX2 解决这个问题?可能使用 unpack/shuffle/permute 内在函数?
最佳答案
我假设您在一个大数组的循环中执行此操作。如果您只使用 __m128i
加载,您将有 15 个有用的字节,这只会在您的 __m256i
输出中产生 20 个输出字节。 (好吧,我猜输出的第 21 个字节会出现,作为输入 vector 的第 16 个字节,新位域的前 8 个字节。但是你的下一个 vector 需要以不同的方式洗牌。)
最好使用 24 字节的输入,产生 32 字节的输出。理想情况下,负载会在中间拆分,因此低 12 字节位于低 128 位“ channel ”中,避免需要像 _mm256_permutexvar_epi32
这样的 channel 交叉洗牌。相反,您可以只_mm256_shuffle_epi8
将字节放在您想要的位置,设置一些移位/和。
// uses 24 bytes starting at p by doing a 32-byte load from p-4.
// Don't use this for the first vector of a page-aligned array, or the last
inline
__m256i unpack12to16(const char *p)
{
__m256i v = _mm256_loadu_si256( (const __m256i*)(p-4) );
// v= [ x H G F E | D C B A x ] where each letter is a 3-byte pair of two 12-bit fields, and x is 4 bytes of garbage we load but ignore
const __m256i bytegrouping =
_mm256_setr_epi8(4,5, 5,6, 7,8, 8,9, 10,11, 11,12, 13,14, 14,15, // low half uses last 12B
0,1, 1,2, 3,4, 4,5, 6, 7, 7, 8, 9,10, 10,11); // high half uses first 12B
v = _mm256_shuffle_epi8(v, bytegrouping);
// each 16-bit chunk has the bits it needs, but not in the right position
// in each chunk of 8 nibbles (4 bytes): [ f e d c | d c b a ]
__m256i hi = _mm256_srli_epi16(v, 4); // [ 0 f e d | xxxx ]
__m256i lo = _mm256_and_si256(v, _mm256_set1_epi32(0x00000FFF)); // [ 0000 | 0 c b a ]
return _mm256_blend_epi16(lo, hi, 0b10101010);
// nibbles in each pair of epi16: [ 0 f e d | 0 c b a ]
}
// Untested: I *think* I got my shuffle and blend controls right, but didn't check.
它使用 clang -O3 -march=znver2
像这样编译 (Godbolt)。当然,内联版本会在循环外加载 vector 常量一次。
unpack12to16(char const*): # @unpack12to16(char const*)
vmovdqu ymm0, ymmword ptr [rdi - 4]
vpshufb ymm0, ymm0, ymmword ptr [rip + .LCPI0_0] # ymm0 = ymm0[4,5,5,6,7,8,8,9,10,11,11,12,13,14,14,15,16,17,17,18,19,20,20,21,22,23,23,24,25,26,26,27]
vpsrlw ymm1, ymm0, 4
vpand ymm0, ymm0, ymmword ptr [rip + .LCPI0_1]
vpblendw ymm0, ymm0, ymm1, 170 # ymm0 = ymm0[0],ymm1[1],ymm0[2],ymm1[3],ymm0[4],ymm1[5],ymm0[6],ymm1[7],ymm0[8],ymm1[9],ymm0[10],ymm1[11],ymm0[12],ymm1[13],ymm0[14],ymm1[15]
ret
在英特尔 CPU 上(在 Ice Lake 之前)vpblendw
仅在端口 5 (https://uops.info/) 上运行,与 vpshufb
竞争(...shuffle_epi8
)。但它是具有直接控制的单个 uop(与 vpblendvb
可变混合不同)。尽管如此,这仍然意味着在英特尔上每 2 个周期最多一个 vector 的后端 ALU 瓶颈。如果你的 src 和 dst 在 L2 缓存中很热(或者可能只有 L1d),那可能是 瓶颈,但这对于前端来说已经是 5 微指令了,所以有了循环开销和存储你我们已经接近前端瓶颈。
与另一个 vpand
/vpor
混合会花费更多的前端 uops,但会减轻 Intel 的后端瓶颈(在 Ice Lake 之前)。在 AMD 上会更糟,其中 vpblendw
可以在 4 个 FP 执行端口中的任何一个上运行,而在 Ice Lake 上更糟,其中 vpblendw
可以在 p1 或 p5 上运行。就像我说的,缓存加载/存储吞吐量可能是比端口 5 更大的瓶颈,因此更少的前端微指令肯定更好地让无序执行看得更远。
这可能不是最优的;也许有一些方法可以通过将偶数(低)和奇数(高)位字段更便宜地放入两个单独输入 vector 的底部 8 字节来设置 vpunpcklwd
?或者进行设置以便我们可以与 OR 混合,而不是需要使用仅在 Skylake 上的端口 5 上运行的 vpblendw
清除一个输入中的垃圾?
或者我们可以用 vpsrlvd
做什么? (但不是 vpsrlvw
- 这需要 AVX-512)。
如果您有 AVX512VBMI,vpmultishiftqb
is a parallel bitfield-extract .您只需要将正确的 3 字节对洗牌到正确的 64 位 SIMD 元素中,然后一个 _mm256_multishift_epi64_epi8
将好的位放在您想要的位置,以及一个 _mm256_and_si256
将每个 16 位字段的高 4 位归零即可。 (不能用 0 掩码处理所有事情,或者将一些零混入多级输入的输入中,因为低 12 位字段不会有任何连续。)或者你可以只设置一个 srli_epi16
同时适用于低和高,而不是需要一个 AND 常量,方法是让 multishift 位域提取将两个输出字段与 16 位元素顶部所需的位对齐。
虽然 vpermb
在 AVX512VBMI 的 CPU 上实际上很快,但不幸的是 Ice Lake 的 vpermw
比 慢vpermb
.
使用 AVX-512 而不是 AVX512VBMI,在 256 位 block 中工作可以让我们做与 AVX2 相同的事情,但避免了混合。相反,使用合并掩码进行右移,或使用带有控制 vector 的 vpsrlvw
仅移动奇数元素。对于 256 位 vector ,这可能与 vpmultishiftqb
一样好。
关于c - SIMD 将 12 位字段解包为 16 位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66347928/
在有些场景下,我们需要对我们的varchar类型的字段做修改,而修改的结果为两个字段的拼接或者一个字段+字符串的拼接。 如下所示,我们希望将xx_role表中的name修改为name+id。
SELECT incMonth as Month, SUM( IF(item_type IN('typ1', 'typ2') AND incMonth = Month, 1, 0 ) )AS
我最近读到 volatile 字段是线程安全的,因为 When we use volatile keyword with a variable, all the threads read its va
我在一些模型中添加了一个 UUID 字段,然后使用 South 进行了迁移。我创建的任何新对象都正确填充了 UUID 字段。但是,我所有旧数据的 UUID 字段为空。 有没有办法为现有数据填充 UUI
刚刚将我的网站从 mysql_ 更新为 mysqli,并破坏了之前正常运行的查询。 我试图从旋转中提取 id,因为它每次都会增加 1,但我不断获取玩家 id,有人可以告诉我我做错了什么吗?我尝试了将
我在 Mac OS X 上使用带有 Sequel Pro 的 MySQL。我想将一个表中的一个字段(即名为“GAME_DY”的列)复制到另一个名为“DAY_ID”的表的空字段中。两个表都是同一数据库的
问题: 是否有可能有一个字段被 JPA 保留但被序列化跳过? 可以实现相反的效果(JPA 跳过字段而序列化则不会),如果使用此功能,那么相反的操作肯定会很有用。 类似这样的事情: @Entity cl
假设我有一个名为“dp”的表 Year | Month | Payment| Payer_ID | Payment_Recipient | 2008/2009 | July
我将尝试通过我的 Raspberry Pi 接入点保证一些 QoS。 开始之前,我先动手:我阅读了有关 tcp、udp 和 ip header 的内容。在IP header description我看
如果你能弄清楚如何重命名这个问题,我愿意接受建议。 在 Dart 语言中,可以编写一个带有 final 字段的类。这些是只能设置的字段构造函数前 body 跑。这可以在声明中(通常用于类中的静态常量)
你怎么样? 我有两个带有两个字段的日期选择器 我希望当用户选择 (From) 时,第二个字段 (TO) 将是 next day 。比如 booking.com 例如:当用户选择From 01-01-2
我想我已经看到了这个问题的一些答案,这些答案可能与我需要的相差不远,但我对 mysql 的了解还不够确定,所以我会根据我的具体情况提出问题。 我有一个包含多个表的数据库,为此,如果“image”表上的
我在 mySQL 数据库中有 2 个表: customers ============ customer_id (1, 2 ) customer_name (john, mark) orders ==
我正在开发一个员工目标 Web 应用程序。 领导/经理在与团队成员讨论后为他们设定目标。这是一年/半年/季度,具体取决于组织遵循的评估周期。 现在的问题是添加基于时间段的字段或存档上一季度/年度数据的
我正在寻找允许内容编辑器从媒体库中选择多个文件的东西,这些文件将在渲染中列出。他们还需要能够上传文件和搜索。它必须在页面编辑器(版本 8 中称为体验编辑器)中工作。 到目前为止我所考虑的: 一堆文件字
现在,我有以下由 original.df %.% group_by(Category) %.% tally() %.% arrange(desc(n)) 创建的 data.frame。 DF 5),
我想知道是否有一些步骤/解决方案可以处理错误消息并将它们放入 Pentaho 工具中的某个字符串或字段中?例如,如果连接到数据库时发生某些错误,则将该消息从登录到字符串/字段。 最佳答案 我们在作业的
如何制作像短信应用程序一样的“收件人”字段?例如,右侧有一个“+”按钮,当添加某人时,名称将突出显示并可单击,如圆角矩形等。有没有内置的框架? 最佳答案 不,但请参阅 Three20 的 TTMess
是否可以获取记录的元素或字段的列表 通过类型信息类似于类的已发布属性的列表吗? 谢谢 ! 最佳答案 取决于您的delphi版本,如果您使用的是delphi 2010或更高版本,则可以使用“新rtti”
我正在构建一个 SQLite 数据库来保存我的房地产经纪人的列表。我已经能够使用外键来识别每个代理的列表,但我想在每个代理的记录中创建一个列表;从代理商和列表之间的一对一关系转变为一对多关系。 看这里
我是一名优秀的程序员,十分优秀!