问题标签 [sse4]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
969 浏览

c - 如何并行比较两个以上的数字?

是否可以使用 SSE4 在一条指令中比较多个数字?

英特尔参考说以下关于 PCMPGTQ

PCMPGTQ - 比较打包数据是否大于

对目标操作数(第一个操作数)和源操作数(第二个操作数)中的压缩四字执行 SIMD 比较。如果第一个(目标)操作数中的数据元素大于第二个(源)操作数中的对应元素,则将目标中对应的数据元素设置为全1;否则,设置为 0。

这并不是我真正想要的,因为我希望能够确定向量中哪些整数更大,哪些更小。

例如,如果我需要比较

我打算放入[32, 13, 44, 99]一个向量和[45, 78, 12, 66]另一个向量,并在一条指令中使用 SSE4 比较它们,并得到[0, 0, 1, 1]结果(0 - 更少,1 - 更大)

但这似乎不是 PCMPGTQ 所做的。有关如何在此级别使用并行性来加速此比较的任何建议?

0 投票
3 回答
21513 浏览

c - 如何在我的计算机上启用对 POPCNT 指令/内在函数的支持?

我试图在我的电脑(Fedora 17 32bit)上运行以下程序。如何使我的系统支持popcnt快速人口计数指令?

我编译了程序并运行它,但得到以下异常:

以下是我的处理器的信息:

0 投票
1 回答
796 浏览

c++ - pcmpestri instruction to write similar strpos function?

How can the pcmpestri instruction be used to write a function similar to strpos function in C++? I can use g++ compiler.

pcmpestri is a new instruction that is found in SSE4

0 投票
2 回答
7923 浏览

c - _mm_crc32_u64 定义不明确

为什么在世界上被_mm_crc32_u64(...)这样定义?

“crc32”指令总是累积 32 位 CRC,而不是64 位 CRC(毕竟,CRC32 不是 CRC64)。如果机器指令 CRC32恰好有一个 64 位目标操作数,则高 32 位将被忽略,并在完成时用 0 填充,因此永远没有 64 位目标。我理解为什么英特尔允许在指令上使用 64 位目标操作数(为了统一),但如果我想快速处理数据,我想要一个尽可能大的源操作数(即,如果我有那么多数据,则为 64 位,尾端更小)并且始终是 32 位目标操作数。但是内在函数不允许 64 位源和 32 位目标。注意其他内在函数:

"crc" 的类型不是 8 位类型,返回类型也不是,它们是 32 位。为什么没有

? 英特尔指令支持这一点,是最有意义的内在。

有没有人有可移植的代码(Visual Studio 和 GCC)来实现后者?谢谢。 我的猜测是这样的:

对于 GCC,以及

对于 VisualStudio。不幸的是,我对约束的工作原理知之甚少,对汇编级编程的语法和语义也没有什么经验。

小编辑:注意我定义的宏:

注意最后一个宏语句有多么不同。缺乏统一性当然表明内在的定义没有得到合理的定义。虽然没有必要(uint64)在最后一个宏中进行显式转换,但它是隐式的并且确实会发生。反汇编生成的代码显示了 32->64 和 64->32 的代码,这两者都是不必要的。

换句话说,它是_mm_crc32_u64不是 _mm_crc64_u64,但他们已经实现了它,就好像它是后者一样。

如果我能得到CRC32正确的上述定义,那么我想将我的宏更改为

0 投票
1 回答
256 浏览

c++ - 使用 sse 的快速紧凑型寄存器

我试图弄清楚如何使用 sse _mm_shuffle_epi8 来压缩 128 位寄存器。

假设我有一个输入变量

基本上是8个16位,表示为:

我的输出称为:

现在我有一个大小为 8 的位向量:

好的,如何根据bit_mask和输入目标得到最终结果?

假设我的位向量是:

那么我希望结果是:

使用 _mm_shuffle_epi8 的任何已知方法?

假设我使用查找数组: _mm_shuffle_epi8(a, mask_lookup[bitvector]);

如何创建数组?

0 投票
1 回答
865 浏览

x86 - 在没有 AVX(2) 的情况下进行 SIMD 收集的最快方法是什么?

假设我有 SSE 到 SSE4.1,但没有 AVX(2),那么加载这样的压缩内存布局的最快方法是什么(所有 32 位整数):

分成四个向量a, b, c, d

我不确定这是否相关,但在我的实际应用程序中,我有 16 个向量,因此a0a1内存中相隔 16*4 字节。

0 投票
1 回答
1293 浏览

c++ - SSE42 & STTNI - PcmpEstrM 比 PcmpIstrM 慢两倍,是真的吗?

我正在尝试使用 SSE42 和 STTNI 指令并且得到了奇怪的结果 - PcmpEstrM(使用显式长度字符串)运行速度比 PcmpIstrM(隐式长度字符串)慢两倍。

  • 在我的i7 3610QM上,差异是2366.2 ms 与 1202.3 ms - 97%
  • i5 3470上差异不是很大,但仍然很重要 = 3206.2 ms 与 2623.2 ms - 22%

两者都是“常春藤桥” - 奇怪的是它们有如此不同的“差异”(至少我在他们的规格中看不到任何技术差异 - http://www.cpu-world.com/Compare_CPUs/Intel_AW8063801013511,Intel_CM8063701093302 /)。

Intel 64 和 IA-32 架构优化参考手册提到 PcmpEstrM 和 PcmpIstrM 的相同吞吐量 = 11 和延迟 = 3。因此,我希望两者的表现相似。

问:是我实际设计/预期的差异还是我以错误的方式使用这些指令?

下面是我的虚拟测试场景(VS 2012)。逻辑非常简单 - 扫描 16MB оf 文本以查找匹配字符。由于 haystack 和 needle string 都不包含零终止符 - 我希望 E 和 I 具有相似的性能。

PS:我尝试在英特尔的开发论坛上发布此问题,但他们将其识别为垃圾邮件:(

0 投票
2 回答
1110 浏览

linux - MOVDQU 指令 + 页边界

我有一个简单的测试程序,它使用 movdqu 指令加载一个 xmm 寄存器,该指令在页面边界(OS = Linux)上访问数据。

如果映射了以下页面,则可以正常工作。如果它没有被映射,那么我会得到一个 SIGSEGV,这可能是预期的。

然而,这大大降低了未对齐负载的有用性。此外,允许未对齐内存引用的 SSE4.2 指令(如 pcmpistri)似乎也表现出这种行为。

这一切都很好——除了我发现有许多使用 pcmpistri 的 strcmp 实现似乎根本没有解决这个问题——而且我已经能够设计出会导致这些实现失败的琐碎测试用例,而一次一个字节的琐碎 strcmp 实现将在相同的数据布局下正常工作。

还有一点需要注意——64 位 Linux 的 GNU C 库实现似乎有一个 __strcmp_sse42 变体,它似乎以更安全的方式使用 pcmpistri 指令。这个 strcmp 的实现相当复杂,但它似乎在小心翼翼地试图避免页面边界问题。我不确定这是由于我上面描述的问题,还是只是试图通过对齐数据来获得更好的性能的副作用。

无论如何,我的问题主要是——我在哪里可以找到更多关于这个问题的信息?我已经输入了“movdqu 跨越页面边界”以及我能想到的谷歌的每一个变体,但没有遇到任何特别有用的东西。如果有人可以向我指出有关这方面的更多信息,将不胜感激。

0 投票
0 回答
545 浏览

alignment - 带有 -xSSE4.1 标志的分段错误

运行使用 -xSSE4.1 编译标志构建的可执行文件时出现分段错误。我在支持 SSE4.1、SSE4.2 和 AVX 的机器上运行它。

导致分段错误的内在函数:

结构定义:

TOT_NUM_PARTS 是一个值为 17 的枚举,而 WORD16 是一个短整数。

gdb 中的“layout asm”命令显示了被转换为的内在代码段:

第 7 行:

0x5cc008 <hme_calc_sad_and_result_num_part_lt_9+136> movdqa 0x22(%r10),%xmm7

给我一个分段错误。

$r10 的值0x7fffd4f22fe0就在执行第 6 行之前;这是一个 16 字节对齐的地址,因此第 6 行执行没有问题。但是第 7 行是从地址加载的,(0x7fffd4f22fe0 + 0x22)该地址不是 16 字节对齐的。gdb 也打印&ps_mv_refine_ctxt->i2_tot_cost[0][0]as 0x7fffd4f22fe0which is $r10 的值。

我担心的是为什么前两个在应该是 movdqu 的时候_mm_loadu_si128翻译成movdqa

当我使用 -xSSE4.2 或 -xAVX 编译标志构建相同的可执行文件时,所有四个 _mm_loadu_si128 指令都被转换为movdqu,因此没有问题。此外,该问题仅在 release-build (-O3 标志)中可见。

我正在使用英特尔 C/C++ 编译器。我觉得__declspec(align(16))结构定义中没有必要。但它不会导致这种奇怪的行为(通过删除它进行测试,发现行为没有变化)。

对不起,很长的帖子。认为这些细节是必要的。

0 投票
0 回答
95 浏览

c++ - _mm_load_ps 是 128 位对齐结构的要求吗?

我有一个与此类似的向量结构设置:它是 128 位对齐的,就像 __m128 类型一样。

我正在使用 SSE 4.1 点积指令 _mm_dp_ps。是否需要为我的以上结构使用 _mm_load_ps 已经对齐 128 位,或者我可以直接转换我的结构吗?这是安全的做法吗?

注意:使用 VS2013 并包含。

使用 _mm_load_ps 的当前代码:

问题代码:

编辑:做了一些测试

使用这个简单的控制台应用程序代码,我运行了 3 个不同的测试。第一次使用 _mm_load_ps,第二次将结构转换为 __m128 类型,最后使用联合内部的 __m128 类型。

结果是: end_a : 26489 滴答 end_b : 19375 滴答 end_c : 18767 滴答

我也单步执行了代码,从 res_a 到 res_c 的所有结果都是正确的。所以这个测试表明使用联合更快。

我知道默认情况下 __m128 类型是对使用的寄存器的引用,而不是类型,但是当包含 smmintrin.h 时,__m128 成为 xmmintrin.h 中定义为的联合

所以我相信使用内在包含执行的指令不是引用寄存器,而是引用 xmmintrin.h 中定义的 __m128 类型。

因此,为了在此测试后更好地重复我的问题:在结构内部使用 xmmintrin.h 中定义的 __m128 结构与 Visual Studio 2013 可用的内在函数一起使用是否安全?